package com.yanqu.road.server.gameplayer.module.drugstore;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.goods.OpenGoodsBagResult;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.drugstore.*;
import com.yanqu.road.entity.drugstore.config.DrugStoreBadgeInfo;
import com.yanqu.road.entity.drugstore.config.DrugStoreDrugUpgradeInfo;
import com.yanqu.road.entity.drugstore.config.DrugStorePrescriptionDispenseInfo;
import com.yanqu.road.entity.drugstore.config.DrugStorePrescriptionInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.player.UserBuilding;
import com.yanqu.road.entity.task.args.DrugStoreRankArgs;
import com.yanqu.road.logic.bussiness.player.DrugStoreBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.logic.helper.WeightHelper;
import com.yanqu.road.pb.activity.RecoveryRewardProto;
import com.yanqu.road.pb.drugstore.DrugStoreProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.BadgeModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.EarnSpeedModule;
import com.yanqu.road.server.gameplayer.module.xiaomian.XiaoMianModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.drugstore.DrugStoreConfigMgr;
import com.yanqu.road.server.manger.drugstore.DrugStoreMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.pb.DrugStorePb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class DrugStoreModule extends GeneralModule {

    private static Logger logger = LogManager.getLogger(DrugStoreModule.class.getName());

    /**
     * 药铺数据
     */
    private UserDrugStoreData userDrugStoreData;

    /**
     * 疑难杂症 玩家数据
     */
    private DrugHardCaseUserData hardCaseUserData;

    /**
     * 疑难杂症 病例记录 k;病例id v：评分排序
     */
    private Map<Integer, List<DrugHardCaseRecordData>> hardCaseRecordListMap = new ConcurrentHashMap<>();

    /**
     * 需要保存的疑难杂症 病例记录
     */
    private List<DrugHardCaseRecordData> saveDrugHardCaseRecordDataList = new ArrayList<>();

    /**
     * 已解锁处方
     */
    private Map<Integer, UserDrugChuFangData> chuFangDataMap;

    /**
     * 已解锁田地数据
     */
    private List<UserDrugLandData> farmLandDataList;

    /**
     * 进行中的订单，包括已完成未领奖
     */
    private List<UserDrugChuFangOrderData> orderDataList;

    /**
     * 已完成已领奖
     */
    private List<UserDrugChuFangOrderData> doneOrderDataList;

    private long lastGetBowlRewardTime;

    private int lastSaveTimePower = -1;					//上线前最后一次保存的用户药铺病人数据 用于找回

    public DrugStoreModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {

        if (!SystemOpenMgr.systemOpen(player, eSystemId.DrugStore.getValue())) {
            return true;
        }

        userDrugStoreData = DrugStoreBussiness.getUserDrugStoreData(player.getUserId());

        if (userDrugStoreData != null){
            lastSaveTimePower = userDrugStoreData.getPower();
        }

        chuFangDataMap = DrugStoreBussiness.getUserDrugChuFangDataMap(player.getUserId());
        farmLandDataList = DrugStoreBussiness.getUserDrugLandDataList(player.getUserId());

        List<UserDrugChuFangOrderData> orderDataListTemp = new ArrayList<>();
        List<UserDrugChuFangOrderData> doneOrderDataListTemp = new ArrayList<>();
        List<UserDrugChuFangOrderData> allOrderList = DrugStoreBussiness.getUserDrugChuFangOrderDataList(player.getUserId());
        for (UserDrugChuFangOrderData orderData : allOrderList) {
            if (orderData.isGetReward()) {
                doneOrderDataListTemp.add(orderData);
            } else {
                orderDataListTemp.add(orderData);
            }
        }

        orderDataList = orderDataListTemp;
        doneOrderDataList = doneOrderDataListTemp;

        if (userDrugStoreData != null) {
            userDrugStoreData.setLandNum(farmLandDataList.size());
        }else {

        }
        // 疑难杂症
        hardCaseUserData = DrugStoreBussiness.getDrugHardCaseUserData(player.getUserId());
        hardCaseRecordListMap = DrugStoreBussiness.getDrugHardCaseRecordDataMap(player.getUserId());

        List<Integer> caseList = new ArrayList<>(hardCaseRecordListMap.keySet());
        caseList.forEach(e->{
            hardCaseRecordSort(e);
        });
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if(userDrugStoreData != null){
            if(userDrugStoreData.isInsertOption()){
                DrugStoreBussiness.addUserDrugStoreData(userDrugStoreData);
            }else if(userDrugStoreData.isUpdateOption()){
                DrugStoreBussiness.updateUserDrugStoreData(userDrugStoreData);
            }

            for (Map.Entry<Integer, UserDrugChuFangData> dataEntry : chuFangDataMap.entrySet()) {
                UserDrugChuFangData chuFangData = dataEntry.getValue();
                if(chuFangData.isInsertOption()){
                    DrugStoreBussiness.addUserDrugChuFangData(chuFangData);
                }else if(chuFangData.isUpdateOption()){
                    DrugStoreBussiness.updateUserDrugChuFangData(chuFangData);
                }
            }

            for (int i = 0; i < farmLandDataList.size(); i++) {
                UserDrugLandData landData = farmLandDataList.get(i);
                if(landData.isInsertOption()){
                    DrugStoreBussiness.addUserDrugLandData(landData);
                }else if(landData.isUpdateOption()){
                    DrugStoreBussiness.updateUserDrugLandData(landData);
                }
            }

            for (int i = 0; i < orderDataList.size(); i++) {
                UserDrugChuFangOrderData orderData = orderDataList.get(i);
                if(orderData.isInsertOption()){
                    DrugStoreBussiness.addUserDrugChuFangOrderData(orderData);
                }else if(orderData.isUpdateOption()){
                    DrugStoreBussiness.updateUserDrugChuFangOrderData(orderData);
                }
            }
        }

        // 疑难杂症数据
        if(hardCaseUserData != null){
            if(hardCaseUserData.isInsertOption()){
                DrugStoreBussiness.addDrugHardCaseUserData(hardCaseUserData);
            }else if(hardCaseUserData.isUpdateOption()){
                DrugStoreBussiness.updateDrugHardCaseUserData(hardCaseUserData);
            }
            List<DrugHardCaseRecordData> tempSaveDrugHardCaseRecordDataList = new ArrayList<>();
            synchronized (saveDrugHardCaseRecordDataList){
                tempSaveDrugHardCaseRecordDataList.addAll(saveDrugHardCaseRecordDataList);
                saveDrugHardCaseRecordDataList.clear();
            }
            for (DrugHardCaseRecordData item : tempSaveDrugHardCaseRecordDataList) {
                if (item.isInsertOption()) {
                    DrugStoreBussiness.addDrugHardCaseRecordData(item);
                } else if (item.isUpdateOption()) {
                    DrugStoreBussiness.updateDrugHardCaseRecordData(item);
                }
            }
        }

        return true;
    }

    @Override
    public void afterLogin() {

        if (!SystemOpenMgr.systemOpen(player, eSystemId.DrugStore.getValue())) {
            return;
        } else {
            if (userDrugStoreData == null) {
                initSystem();
            }
        }
        //重登，处理所有队列
        //if(isAutoOrderReward() && isAutoHarvest()) {
        //    offLineHandle(Long.MAX_VALUE);
        //}

        syncDrugStoreData();

        syncReaHot();

        clearActivityDataOutTime();

        DrugStoreMgr.synDrugStoreDispenseRankCaseList(player.getUserId());
    }

    /**
     * 清理过期的活动数据
     */
    private void clearActivityDataOutTime() {
        Map<Integer, DrugActivityRankValue> rankActivityDataMap = userDrugStoreData.getRankActivityDataMap();
        if (rankActivityDataMap == null || rankActivityDataMap.isEmpty()) {
            return;
        }
        synchronized (rankActivityDataMap) {
            List<Integer> needRemoveList = new ArrayList<>();
            for (DrugActivityRankValue activityData : rankActivityDataMap.values()) {
                List<Integer> activityIdList = NormalActivityMgr.getOpenDrugStoreRankActivityIdList();
                if (!activityIdList.contains(activityData.getActivityId())) {
                    needRemoveList.add(activityData.getActivityId());
                }
            }
            if (needRemoveList.size() > 0) {
                for (Integer activityId : needRemoveList) {
                    rankActivityDataMap.remove(activityId);
                }
                userDrugStoreData.setUpdateOption();
            }
        }
    }

    /**
     * 下发店铺数据
     */
    public void syncDrugStoreData() {
        if (userDrugStoreData != null) {
            checkBuffEndTime();
            recoverUserEnergyPower();
            DrugStoreProto.DrugStoreUserDataSync.Builder syncMsg = DrugStoreProto.DrugStoreUserDataSync.newBuilder();
            syncMsg.setUserData(getUserDataBuilder());
            syncMsg.setHardCaseUserInfo(builderDrugStoreHardCaseUserInfo());
            player.sendPacket(Protocol.U_DRUG_STORE_DATA_SYNC, syncMsg);
        }
    }

    /**
     * 下发红点
     */
    public void syncReaHot() {
        if (userDrugStoreData == null) {
            return;
        }
        //

    }

    public void syncStoreBuffValue(){
        if (userDrugStoreData == null){
            return;
        }
        checkBuffEndTime();
        DrugStoreProto.DrugStoreBuffValueSync.Builder syncMsg = DrugStoreProto.DrugStoreBuffValueSync.newBuilder();
        syncMsg.setBuffValue(userDrugStoreData.getBuffValue().getBuffValue());
        syncMsg.setBuffEndTime(userDrugStoreData.getBuffValue().getEndTime());
        player.sendPacket(Protocol.U_DRUG_STORE_BUFF_VALUE_SYNC, syncMsg);
    }

    public void checkBuffEndTime(){
        if(userDrugStoreData == null){
            return;
        }
        if(userDrugStoreData.getBuffValue().getEndTime() > 0 && userDrugStoreData.getBuffValue().getEndTime() < DateHelper.getCurrentTime()){
            userDrugStoreData.setBuffValue(new DrugStoreBuffValue());
        }
    }

    /**
     * 初始系统
     */
    public void initSystem() {

        if (!SystemOpenMgr.systemOpen(player, eSystemId.DrugStore.getValue())) {
            return;
        }

        if (userDrugStoreData != null) {
            return;
        }

        userDrugStoreData = new UserDrugStoreData();
        userDrugStoreData.setPower(GameConfig.DRUGSTORE_POWER_MAX);
        userDrugStoreData.setLastRecoverPowerTime(System.currentTimeMillis());
        userDrugStoreData.setUserId(player.getUserId());
        userDrugStoreData.setDrugStoreLv(1);
        userDrugStoreData.setDrugNumMap(new ConcurrentHashMap<>());
        //赠送2个甘草
        userDrugStoreData.addDrugNum(eItemId.DRUG_STORE_GAN_CAO.getValue(), 2);

        farmLandDataList = new ArrayList<>();
        DrugStoreBadgeInfo badgeInfo = DrugStoreConfigMgr.getDrugStoreBadgeInfo(userDrugStoreData.getDrugStoreLv());
        if (badgeInfo != null) {
            //默认解锁的诊桌
            unLockDoctorTable();
            //解锁田地
            unLockLandData();
            // 初始化厢房徽章
            updateBadge();
        }
        //默认工艺
        List<Integer> techList = StringUtils.stringToIntegerList(GameConfig.DRUGSTORE_WORK_ID, "\\|");
        for (int tech : techList) {
            DrugStoreTeach teach = new DrugStoreTeach();
            teach.setId(tech);
            teach.setLv(1);
            userDrugStoreData.getTechList().add(teach);
        }
        notifyDrugStoreTechLevel();

        //默认解锁的药材
        unLockDrug();
        userDrugStoreData.setInsertOption();

        //默认解锁的处方
        chuFangDataMap = new ConcurrentHashMap<>();
        unLockChuFang();

        orderDataList = new ArrayList<>();
        doneOrderDataList = new ArrayList<>();

        // 解锁疑难杂症数据
        getDrugHardCaseUserData(true);
    }

    /**
     * 解锁处方
     */
    private void unLockChuFang() {
        List<DrugStorePrescriptionInfo> chuFangList = DrugStoreConfigMgr.getUnLock(userDrugStoreData.getDrugStoreLv());
        for (DrugStorePrescriptionInfo info : chuFangList) {
            if (chuFangDataMap.containsKey(info.getId())) {
                continue;
            }
            UserDrugChuFangData chuFangData = new UserDrugChuFangData();
            chuFangData.setUserId(userDrugStoreData.getUserId());
            chuFangData.setChuFang(info.getId());
            chuFangData.setLv(1);
            chuFangData.setInsertOption();
            chuFangDataMap.put(chuFangData.getChuFang(), chuFangData);
        }
        notifyDrugStoreChuFangLevel();
    }

    /**
     * 处方成就
     */
    private void notifyDrugStoreChuFangLevel() {
        int allLv = 0;
        for (Map.Entry<Integer, UserDrugChuFangData> dataEntry : chuFangDataMap.entrySet()) {
            allLv += dataEntry.getValue().getLv();
        }
        player.notifyListener(eGamePlayerEventType.DrugStoreChuFangLevel.getValue(), BigInteger.valueOf(allLv));
    }

    /**
     * 工艺成就
     */
    private void notifyDrugStoreTechLevel() {
        int allLv = 0;
        for (int i = 0; i < userDrugStoreData.getTechList().size(); i++) {
            DrugStoreTeach teach = userDrugStoreData.getTechList().get(i);
            allLv += teach.getLv();
        }
        player.notifyListener(eGamePlayerEventType.DrugStoreTechLevel.getValue(), BigInteger.valueOf(allLv));
    }

    /**
     * 病人数成就
     */
    private void notifyDrugStoreReceiveNum(int times) {
        player.notifyListener(eGamePlayerEventType.DrugStoreReceiveNumLevel.getValue(), BigInteger.valueOf(userDrugStoreData.getReceiveNum()));
        player.notifyListener(eGamePlayerEventType.DrugStoreBusinessTimes.getValue(), times);
        //加一下平台接口数据
        player.getModule(XiaoMianModule.class).addDrugStoreBusinessTimes(times);
    }

    /**
     * 解锁药材
     */
    private void unLockDrug() {
        List<Integer> newList = DrugStoreMgr.getUnLockDrug(userDrugStoreData.getDrugStoreLv());
        for (int drugId : newList) {
            userDrugStoreData.addUnLockDrug(drugId);
        }
    }

    /**
     * 解锁诊桌
     */
    private void unLockDoctorTable() {
        for (int tableId : DrugStoreConfigMgr.getBadgeInfoSpecialEffect(userDrugStoreData.getDrugStoreLv(), 2)) {
            if (getDrugStoreDoctorTable(tableId) == null) {
                DrugStoreDoctorTable table = new DrugStoreDoctorTable();
                table.setTableId(tableId);
                table.setDoctorId(tableId);
                table.setLastCuredTime(System.currentTimeMillis());
                userDrugStoreData.getDoctorTableList().add(table);
            }
        }
    }

    /**
     * 解锁田地
     */
    private void unLockLandData() {
        //默认解锁的田地
        for (int landId : DrugStoreConfigMgr.getBadgeInfoSpecialEffect(userDrugStoreData.getDrugStoreLv(), 1)) {
            if (getFarmLandData(landId) == null) {
                UserDrugLandData landData = new UserDrugLandData();
                landData.setUserId(player.getUserId());
                landData.setLandId(landId);
                landData.setLastMatureTime(System.currentTimeMillis());
                landData.setInsertOption();
                farmLandDataList.add(landData);
            }
        }
        userDrugStoreData.setLandNum(farmLandDataList.size());
    }

    /**
     * 病人获得(体力恢复)
     */
    public void recoverUserEnergyPower() {
        if (userDrugStoreData == null) {
            return;
        }

        CalcPowerResult calcPowerResult = PowerHelper.calcPower(userDrugStoreData.getLastRecoverPowerTime() / 1000,
                GameConfig.DRUGSTORE_POWER_CD * DateHelper.MINUTE_SECONDS, GameConfig.DRUGSTORE_POWER_RENUM, GameConfig.DRUGSTORE_POWER_MAX, userDrugStoreData.getPower());
        //日志
        if(userDrugStoreData.getPower() != calcPowerResult.getCurPower()){
            AutoLogMgr.add(new LogDrugStoreEnergy(player.getUserId(), 1, userDrugStoreData.getPower(), calcPowerResult.getCurPower() - userDrugStoreData.getPower(), calcPowerResult.getCurPower()));
        }
        userDrugStoreData.setPower(calcPowerResult.getCurPower());
        userDrugStoreData.setLastRecoverPowerTime(calcPowerResult.getLastRecoverTime() * 1000);
    }

    /**
     * 营业/病人排队
     */
    public int receivePatient() {

        int checkResult = receptCheck(false);
        if (checkResult != 0) {
            return checkResult;
        }

        //随机处方
        DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.randomUnLockChuFang(userDrugStoreData.getDrugStoreLv());
        if (prescriptionInfo == null) {
            return GameErrorCode.E_DRUG_STORE_CHU_FANG_CONFIG_EXIST;
        }

        UserDrugChuFangData chuFangData = getUserDrugChuFangData(prescriptionInfo.getId());
        if (chuFangData == null) {
            return GameErrorCode.E_DRUG_STORE_CHU_FANG_UNLOCK;
        }

        synchronized (userDrugStoreData) {

            AutoLogMgr.add(new LogDrugStoreEnergy(player.getUserId(), 3, userDrugStoreData.getPower(), 1, userDrugStoreData.getPower() - 1));

            //体力减1
            userDrugStoreData.setPower(userDrugStoreData.getPower() - 1);
            //队列加1
            userDrugStoreData.setMaxQueueId(userDrugStoreData.getMaxQueueId() + 1);
            //接待人数
            userDrugStoreData.setReceiveNum(userDrugStoreData.getReceiveNum() + 1);
            DrugStoreQueue queue = new DrugStoreQueue();
            queue.setqId(userDrugStoreData.getMaxQueueId());
            if(userDrugStoreData.getMaxQueueId() == 1){
                queue.setCf(1001);
                prescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(1001);
            }else {
                queue.setCf(chuFangData.getChuFang());
            }
            queue.setqT(System.currentTimeMillis());
            List<Integer> dialogList = StringUtils.stringToIntegerList(prescriptionInfo.getDialoguePeople(), "\\|");
            //随机对话
            queue.setdId(new Random().nextInt(dialogList.size()));

            userDrugStoreData.getNpcQueueList().add(queue);
            notifyDrugStoreReceiveNum(1);
            backendCal(false);
        }
        AutoLogMgr.add(new LogDrugStoreReceive(player.getUserId(), 1, 1));


        //同步给客户端
        DrugStoreProto.DrugReceptPatientRespMsg.Builder builder = getReceptPatientRespBuilder();
        player.sendPacket(Protocol.U_DRUG_STORE_RECEPT_PATIENT, builder);

        //接待数达到解锁条件
        if(userDrugStoreData.getReceiveNum() == GameConfig.DRUGSTORE_UNLOCK_AUTO_LIMIT){
            syncDrugStoreData();
        }

        if (userDrugStoreData.getPower() <= 0) {
            player.notifyListener(eGamePlayerEventType.RechargeDrugStoreNew.getValue(), 0);
        }
        try {
            clinicRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
        return 0;
    }

    /**
     * 一键，营业/病人排队
     */
    /**
     * 一键，营业/病人排队
     * @param respMsg
     * @param assistantFlag 是否是小玉助手
     * @return
     */
    public int receivePatientOneKey(DrugStoreProto.DrugReceptPatientRespMsg.Builder respMsg, boolean assistantFlag) {

        int checkResult = receptCheck(assistantFlag);
        if (checkResult != 0) {
            return checkResult;
        }

        if(userDrugStoreData.getReceiveNum() < GameConfig.DRUGSTORE_UNLOCK_AUTO_LIMIT){
            return GameErrorCode.E_DRUG_STORE_ONE_KEY_RECEPT_LOCK;
        }

        synchronized (userDrugStoreData) {
            //接收人数
            int addNum = Math.min(userDrugStoreData.getPower(), GameConfig.DRUGSTORE_WAIT_MAX_NUM - userDrugStoreData.getNpcQueueList().size());
            AutoLogMgr.add(new LogDrugStoreEnergy(player.getUserId(), 3, userDrugStoreData.getPower(), addNum, userDrugStoreData.getPower() - addNum));
            Random random = new Random();
            for (int i = 0; i < addNum; i++) {
                //随机处方
                DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.randomUnLockChuFang(userDrugStoreData.getDrugStoreLv());
                if (prescriptionInfo == null) {
                    continue;
                }
                UserDrugChuFangData chuFangData = getUserDrugChuFangData(prescriptionInfo.getId());
                if (chuFangData == null) {
                    continue;
                }
                //体力减1
                userDrugStoreData.setPower(userDrugStoreData.getPower() - 1);
                //队列加1
                userDrugStoreData.setMaxQueueId(userDrugStoreData.getMaxQueueId() + 1);
                //接待人数
                userDrugStoreData.setReceiveNum(userDrugStoreData.getReceiveNum() + 1);
                DrugStoreQueue queue = new DrugStoreQueue();
                queue.setqId(userDrugStoreData.getMaxQueueId());
                queue.setCf(chuFangData.getChuFang());
                queue.setqT(System.currentTimeMillis());
                List<Integer> dialogList = StringUtils.stringToIntegerList(prescriptionInfo.getDialoguePeople(), "\\|");
                //随机对话
                queue.setdId(random.nextInt(dialogList.size()));
                userDrugStoreData.getNpcQueueList().add(queue);
                if(respMsg != null){
                    respMsg.addWaitNpc(DrugStorePb.buildDrugStoreQueueTemp(queue));
                }
            }
            notifyDrugStoreReceiveNum(addNum);

            if(respMsg == null) {
                backendCal(false);
            }else {
                syncDrugStoreData();
            }

            AutoLogMgr.add(new LogDrugStoreReceive(player.getUserId(), 2, addNum));
        }

        //同步给客户端
        DrugStoreProto.DrugReceptPatientRespMsg.Builder builder = getReceptPatientRespBuilder();
        player.sendPacket(Protocol.U_DRUG_STORE_RECEPT_PATIENT, builder);

        if (userDrugStoreData.getPower() <= 0) {
            if (!assistantFlag) {
                player.notifyListener(eGamePlayerEventType.RechargeDrugStoreNew.getValue(), 0);
            }
        }
        try {
            clinicRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
        return 0;
    }

    /**
     * 使用道具恢复体力
     */
    public int usePowerAddItem(int count) {
        if (count <= 0) {
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(GameConfig.DRUGSTORE_ITEM_ID_SIGN);
        if (goodsInfo == null) {
            return GameErrorCode.E_DRUG_STORE_CONFIG_NOT_EXIST;
        }
        if (!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.DRUGSTORE_ITEM_ID_SIGN, BigInteger.valueOf(count)),
                eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreAddPowerConsumer)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        //先同步一下体力
        recoverUserEnergyPower();
        int powerGet = goodsInfo.getParamList().get(0).intValue() * count;
        userDrugStoreData.setPower(userDrugStoreData.getPower() + powerGet);

        AutoLogMgr.add(new LogDrugStoreEnergy(player.getUserId(), 2, userDrugStoreData.getPower() - powerGet, powerGet, userDrugStoreData.getPower()));

        DrugStoreProto.DrugStorePowerAddItemRespMsg.Builder respMsg = DrugStoreProto.DrugStorePowerAddItemRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setPower(userDrugStoreData.getPower());
        respMsg.setLastRecoverPowerTime(userDrugStoreData.getLastRecoverPowerTime());
        player.sendPacket(Protocol.U_DRUG_STORE_USE_POWER_ITEM, respMsg);
        try {
            clinicRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
        return 0;
    }

    //计算什么时候会满，微信提示
    private void clinicRecoveryTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        long nowTime = System.currentTimeMillis();
        long recoveryTime = 0;

        int maxEnergy = GameConfig.DRUGSTORE_POWER_MAX;
        long energyRestoreTime = GameConfig.DRUGSTORE_POWER_CD * DateHelper.MINUTE_MILLIONS;
        if(userDrugStoreData.getPower() < maxEnergy){
            recoveryTime = nowTime + energyRestoreTime * (maxEnergy - userDrugStoreData.getPower());
        }
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setClinicTime(recoveryTime);
    }

    private DrugStoreProto.DrugReceptPatientRespMsg.Builder getReceptPatientRespBuilder() {
        DrugStoreProto.DrugReceptPatientRespMsg.Builder builder = DrugStoreProto.DrugReceptPatientRespMsg.newBuilder().setRet(0);
        builder.setPower(userDrugStoreData.getPower());
        builder.setLastRecoverPowerTime(userDrugStoreData.getLastRecoverPowerTime());
        for (int i = 0; i < userDrugStoreData.getNpcQueueList().size(); i++) {
            DrugStoreQueue storeQueue = userDrugStoreData.getNpcQueueList().get(i);
            builder.addWaitNpc(DrugStorePb.buildDrugStoreQueueTemp(storeQueue));
        }
        return builder;
    }

    /**
     * 领取订单收益
     */
    public int getOrderReward(long orderNo) {

        if (isAutoOrderReward()) {
            //解锁账房先生后
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        Property reward = new Property();
        DrugStoreProto.DrugStoreShuLianDuSync.Builder shuLianDuSync = DrugStoreProto.DrugStoreShuLianDuSync.newBuilder();
        UserDrugChuFangOrderData orderData;
        int chuFangLv;
        synchronized (userDrugStoreData) {
            orderData = getUserDrugChuFangOrderData(orderNo);
            if (orderData == null) {
                return GameErrorCode.E_DRUG_STORE_ORDER_NOT_EXIST;
            }
            if (orderData.getState() == 0) {
                return GameErrorCode.E_DRUG_STORE_ORDER_NOT_COMPLETE;
            }
            if (orderData.getState() == 2) {
                return GameErrorCode.E_DRUG_STORE_ORDER_GOT_REWARD;
            }

            //处方配置
            DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(orderData.getChuFang());
            if (prescriptionInfo == null) {
                return GameErrorCode.E_DRUG_STORE_CHU_FANG_CONFIG_EXIST;
            }

            chuFangLv = chuFangDataMap.get(orderData.getChuFang()).getLv();
            int rewardTime = (int)(orderData.getReceiveTime() == 0 ? orderData.getOrderTime() /1000 : orderData.getReceiveTime() /1000);
            DrugOrderReward orderReward = calOrderReward(orderData.getChuFang(), chuFangLv, orderData.getProcess(), rewardTime);
            orderData.setChuFangLv(chuFangLv);
            reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(orderReward.getExp()));
            reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(orderReward.getTb()));
            //熟练度
            UserDrugChuFangData chuFangData = getChuFangDataMap().get(orderData.getChuFang());
            if(chuFangData != null){
                chuFangData.setShuLianDu(chuFangData.getShuLianDu() + orderReward.getSld());
                shuLianDuSync.addChuFang(DrugStorePb.buildDrugChuFangTemp(chuFangData));
            }

            orderData.setState(2);
            orderData.setNeedSync(true);
            orderData.setGetReward(true);
            orderData.setGetRewardTime(System.currentTimeMillis());
            orderData.setReward(PropertyHelper.parsePropertyToString(reward));
            updateTableLastDoneTime(orderData.getTable(), orderData.getGetRewardTime());
            backendCal(false);

            addActivityScoreRiseData(reward.getCountByGoodsId(GameConfig.DRUGSTORE_ITEM_ID_MONEY).intValue(), 1, orderReward.getT());
        }

        userDrugStoreData.setTongBi(reward.getCountByGoodsId(GameConfig.DRUGSTORE_ITEM_ID_MONEY).intValue() + userDrugStoreData.getTongBi());

        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreOrderReward);

        //冲榜
        player.notifyListener(eGamePlayerEventType.DrugStoreTongBiCrossUserRank.getValue(), new DrugStoreRankArgs(userDrugStoreData.getRankActivityDataMap()));
        player.notifyListener(eGamePlayerEventType.DrugStoreTongBiUserRank.getValue(), new DrugStoreRankArgs(userDrugStoreData.getRankActivityDataMap()));
        changeValueRank();

        //日志
        AutoLogMgr.add(new LogDrugStoreOrder(player.getUserId(), orderNo, new Date(orderData.getOrderTime()), new Date(orderData.getReceiveTime() == 0 ? orderData.getOrderTime() : orderData.getReceiveTime()),
                new Date(orderData.getFinishTime()), orderData.getChuFang(), chuFangLv, 1, "",
                PropertyHelper.parsePropertyToString(reward)));

        DrugStoreProto.DrugGetRewardRespMsg.Builder respMsg = DrugStoreProto.DrugGetRewardRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        respMsg.setExperience(userDrugStoreData.getExperience());
        respMsg.setTongBi(userDrugStoreData.getTongBi());

        player.sendPacket(Protocol.U_DRUG_STORE_GET_ORDER_REWARD, respMsg);
        player.sendPacket(Protocol.U_DRUG_STORE_SHU_LIAN_DU_SYNC, shuLianDuSync);
        return 0;
    }

    /**
     * 计算处方收益
     * @param chuFang 处方id
     * @param lv 处方等级
     * @param needList 处方药材需求
     * @param time 获得时间
     * @return
     */
    private DrugOrderReward calOrderReward(int chuFang, int lv, List<DrugOrderNeed> needList, int time) {
        DrugOrderReward reward = new DrugOrderReward();
        reward.setCf(chuFang);
        reward.setLv(lv);
        reward.setT(time);
        DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(chuFang);
        checkBuffEndTime();
        DrugStoreBuffValue buffValue = userDrugStoreData.getBuffValue();
        if(prescriptionInfo != null){
            List<Integer> expList = StringUtils.stringToIntegerList(prescriptionInfo.getGetExp(), "\\|");
            reward.setExp(expList.get(0) + getChuFangExReward(chuFang, 2));
            int tongBi = 0;
            //药方收益: （药材数量 * 单价 * （1+难度加成） + 额外收益） * （1+buff）
            //处方药材收益
            for (DrugOrderNeed need : needList) {
                tongBi += getChuFangDrugTongBi(prescriptionInfo, need);
            }
            //处方额外收益
            tongBi += getChuFangExReward(chuFang, 1);

            //藏品加成
            long addition = CurioMgr.getSkillAdditionBySkillType(eSkillType.DrugStoreTongBiSkill.getValue(), player, 0);

            //buff加成
            if(buffValue.getEndTime() > 0){
                addition += buffValue.getBuffValue();
            }

            tongBi = BigDecimal.valueOf(tongBi).multiply(BigDecimal.valueOf(1000 + addition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).intValue();

            reward.setTb(tongBi);

            //熟练度
            if(expList.size() > 1) {
                reward.setSld(expList.get(1));
            }
        }
        return reward;
    }

    /**
     * 种植收获
     */
    public int getPlanDrugReward(int landId) {

        DrugStoreProto.DrugPlantGetRewardRespMsg.Builder respMsg = DrugStoreProto.DrugPlantGetRewardRespMsg.newBuilder();
        respMsg.setRet(0);

        synchronized (userDrugStoreData) {
            if (!isAutoHarvest()) {
                //沒有补药师，才可以手动收获
                UserDrugLandData landData = getFarmLandData(landId);
                if (landData.getDrugId() == 0) {
                    //未种植
                    respMsg.setRet(GameErrorCode.E_DRUG_STORE_LAND_NOT_PLANED);
                }else {

                    if (landData.getMatureTime() > System.currentTimeMillis()) {
                        //未成熟
                        respMsg.setRet(GameErrorCode.E_DRUG_STORE_LAND_NOT_MATURE);
                    } else {

                        //设置完成时间；作为抓药结束的时间
                        landData.setLastMatureTime(System.currentTimeMillis());
                        landData.setState(2);

                        //日志
                        AutoLogMgr.add(new LogDrugStorePlant(player.getUserId(), landId, landData.getDrugId(), 1, new Date(landData.getPlantTime()), new Date(landData.getMatureTime())));

                        Property reward = handleLandHarvestForManualPlant(landData);
                        if (!reward.isNothing()) {
                            respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
                        } else {
                            respMsg.setRet(GameErrorCode.E_DRUG_STORE_LAND_NOT_PLANED);
                        }
                        respMsg.setLand(DrugStorePb.buildDrugLandTemp(landData));
                    }
                }
            } else {

            }
        }

        player.sendPacket(Protocol.U_DRUG_STORE_PLANT_GET_REWARD, respMsg);

        return 0;
    }

    /**
     * 领取聚宝盆
     */
    public int getTreasureBowlReward() {

        if (lastGetBowlRewardTime > 0 && System.currentTimeMillis() - lastGetBowlRewardTime < 5000) {
            return GameErrorCode.E_REQUEST_TOO_FAST;
        }
        lastGetBowlRewardTime = System.currentTimeMillis();

        Property reward = new Property();
        DrugStoreProto.DrugStoreShuLianDuSync.Builder shuLianDuSync = DrugStoreProto.DrugStoreShuLianDuSync.newBuilder();
        synchronized (userDrugStoreData) {
            if (userDrugStoreData.getRewardList().size() == 0) {
                return GameErrorCode.E_DRUG_STORE_NO_REWARD_AT_MOMENT;
            }
            List<DrugOrderReward> orderRewardList = userDrugStoreData.getRewardList();

            for (DrugOrderReward orderReward : orderRewardList) {
                DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(orderReward.getCf());
                if (prescriptionInfo == null) {
                    continue;
                }
                reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(orderReward.getExp()));
                reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(orderReward.getTb()));
                //熟练度
                UserDrugChuFangData chuFangData = getChuFangDataMap().get(orderReward.getCf());
                if(chuFangData != null){
                    chuFangData.setShuLianDu(chuFangData.getShuLianDu() + orderReward.getSld());
                    shuLianDuSync.addChuFang(DrugStorePb.buildDrugChuFangTemp(chuFangData));
                }
                addActivityScoreRiseData((int)orderReward.getTb(), 1, orderReward.getT());
            }
            userDrugStoreData.setRewardList(new ArrayList<>());
            userDrugStoreData.setTongBi(reward.getCountByGoodsId(GameConfig.DRUGSTORE_ITEM_ID_MONEY).intValue() + userDrugStoreData.getTongBi());
        }

        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreBowlReward);

        //冲榜
        player.notifyListener(eGamePlayerEventType.DrugStoreTongBiCrossUserRank.getValue(), new DrugStoreRankArgs(userDrugStoreData.getRankActivityDataMap()));
        player.notifyListener(eGamePlayerEventType.DrugStoreTongBiUserRank.getValue(), new DrugStoreRankArgs(userDrugStoreData.getRankActivityDataMap()));
        changeValueRank();

        DrugStoreProto.DrugTreasureBowlRewardRespMsg.Builder respMsg = DrugStoreProto.DrugTreasureBowlRewardRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        respMsg.setExperience(userDrugStoreData.getExperience());
        respMsg.setTongBi(userDrugStoreData.getTongBi());
        player.sendPacket(Protocol.U_DRUG_STORE_GET_TREASURE_BOWL_REWARD, respMsg);
        player.sendPacket(Protocol.U_DRUG_STORE_SHU_LIAN_DU_SYNC, shuLianDuSync);
        return 0;
    }

    /**
     * 获取处方额外收益
     *
     * @param chuFang 处方
     * @param type 1:铜币；2：经验
     * @return
     */
    private int getChuFangExReward(int chuFang, int type) {
        int extNum = 0;
        UserDrugChuFangData chuFangData = getUserDrugChuFangData(chuFang);
        if (chuFangData != null) {
            DrugStoreDrugUpgradeInfo upgradeInfo = DrugStoreConfigMgr.getDrugStoreDrugUpgradeInfo(chuFangData.getChuFang(), chuFangData.getLv());
            if (upgradeInfo != null) {
                List<Integer> numList = StringUtils.stringToIntegerList(upgradeInfo.getExParam(), "\\|");
                if(type == 1){
                    extNum = numList.get(0);
                }else if(type == 2 && numList.size() > 1){
                    extNum = numList.get(1);
                }
            }
        }
        return extNum;
    }

    /**
     * 获取处方的药材收益
     *
     * @param prescriptionInfo 处方配置
     * @param need             药材需求
     * @return
     */
    private int getChuFangDrugTongBi(DrugStorePrescriptionInfo prescriptionInfo, DrugOrderNeed need) {
        int tongBi = 0;
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(need.getItemId());
        if (goodsInfo != null) {
            //药方收益: 药材数量 * 单价 * （1+难度加成）
            tongBi = BigDecimal.valueOf(need.getNeedNum() * goodsInfo.getParamList().get(1).intValue() * (1000 + DrugStoreMgr.getChuFangMakeDifficultAdd(prescriptionInfo.getMakeLv())))
                    .divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_DOWN).intValue();
        }
        return tongBi;
    }

    /**
     * 背包详情
     */
    public void bagDetail() {
        DrugStoreProto.DrugStoreDrugBagRespMsg.Builder respMsg = DrugStoreProto.DrugStoreDrugBagRespMsg.newBuilder();
        if (userDrugStoreData != null) {
            List<UserDrugChuFangOrderData> list = new ArrayList<>(orderDataList);
            Map<Integer, Integer> orderItemMap = new HashMap<>();
            for (UserDrugChuFangOrderData orderData : list) {
                if(orderData.getState() > 0){
                    continue;
                }
                for (DrugOrderNeed process : orderData.getProcess()) {
                    int num = orderItemMap.getOrDefault(process.getItemId(), 0);
                    orderItemMap.put(process.getItemId(), num + process.getPlanNum());
                }
            }
            for (Map.Entry<Integer, Integer> entry : userDrugStoreData.getDrugNumMap().entrySet()) {
                DrugStoreProto.DrugItemTemp.Builder builder = DrugStoreProto.DrugItemTemp.newBuilder();
                builder.setItemId(entry.getKey());
                //加上订单的数量
                builder.setItemNum(entry.getValue() + orderItemMap.getOrDefault(entry.getKey(), 0));
                respMsg.addBag(builder);
            }
        } else {

        }
        player.sendPacket(Protocol.U_DRUG_STORE_DRUG_BAG, respMsg);
    }

    /**
     * 土地builder
     */
    private DrugStoreProto.DrugStoreLandDataSync.Builder getLandSyncBuilder() {
        DrugStoreProto.DrugStoreLandDataSync.Builder syncMsg = DrugStoreProto.DrugStoreLandDataSync.newBuilder();
        for (int i = 0; i < farmLandDataList.size(); i++) {
            syncMsg.addLand(DrugStorePb.buildDrugLandTemp(farmLandDataList.get(i)));
        }
        return syncMsg;
    }

    /**
     * 处理田地收获（手动收获）
     * 寻找订单，不进入背包
     */
    private Property handleLandHarvestForManualPlant(UserDrugLandData landData) {
        Property reward = new Property();
        if (landData.getState() != 2) {
            return reward;
        }
        boolean fillDone = false;
        List<UserDrugChuFangOrderData> orderList = getOrderListByStartPlantTime();
        for (int i = 0; i < orderList.size(); i++) {
            UserDrugChuFangOrderData orderData = orderList.get(i);
            if(orderData.getState() > 0){
                continue;
            }
            if(fillDone){
                break;
            }
            for (DrugOrderNeed process : orderData.getProcess()) {
                if(process.getItemId() != landData.getDrugId()){
                    continue;
                }
                if(process.getNeedNum() <= process.getPlaningNum() + process.getBagNum() + process.getPlanNum()){
                    continue;
                }
                fillDone = true;
                process.setPlanNum(1 + process.getPlanNum());
                process.setEndTime(System.currentTimeMillis());
                orderData.setNeedSync(true);
                orderData.setUpdateOption();
                //日志
                AutoLogMgr.add(new LogDrugStoreDrug(player.getUserId(), landData.getDrugId(), 1, 1, 1, process.getPlanNum(), orderData.getNo(), new Date(landData.getMatureTime())));
                break;
            }
        }
        if(!fillDone){
            //进背包
            userDrugStoreData.addDrugNum(landData.getDrugId(), 1);
            //日志
            AutoLogMgr.add(new LogDrugStoreDrug(player.getUserId(), landData.getDrugId(), 1, 1, 1, userDrugStoreData.getDrugNum(landData.getDrugId()), 0, new Date(landData.getMatureTime())));
        }
        reward.addProperty(landData.getDrugId(), BigInteger.ONE);
        //土地置空
        clearLandData(landData);
        return reward;
    }

    /**
     * 处理田地收获
     */
    private Property handleLandHarvest(UserDrugLandData landData) {
        Property reward = new Property();
        if (landData.getState() != 2) {
            return reward;
        }
        if (landData.getPlanId() > 0) {
            UserDrugChuFangOrderData orderData = getUserDrugChuFangOrderData(landData.getOrderNo());
            if (orderData == null) {
                //进背包
                userDrugStoreData.addDrugNum(landData.getDrugId(), 1);
            } else {
                //供应订单
                supplyOrderDrug(landData, orderData);
            }
        } else {
            //进背包
            userDrugStoreData.addDrugNum(landData.getDrugId(), 1);
        }

        reward.addProperty(landData.getDrugId(), BigInteger.ONE);
        //土地置空
        clearLandData(landData);
        return reward;
    }

    /**
     * 计算背包剩余药材
     * @param orderData
     */
    private void calAutoBagToOrderNeed(UserDrugChuFangOrderData orderData) {
        //计算背包剩余药材
        for (DrugOrderNeed need : orderData.getProcess()) {
            Map<Integer, Integer> bagMap = calBagStock();
            if(calBagToOrderNeed(bagMap, need)){
                orderData.setNeedSync(true);
                orderData.setUpdateOption();
            }
        }
    }

    /**
     * 背包已有药材分配给需求
     * @param bagMap 背包药材最新数据
     * @param need  药材需求
     */
    private boolean calBagToOrderNeed(Map<Integer, Integer> bagMap, DrugOrderNeed need) {
        boolean changed = false;
        int needNum = need.getNeedNum() - need.getBagNum() - need.getPlanNum() - need.getPlaningNum();
        int hadNum = bagMap.getOrDefault(need.getItemId(), 0);
        if (hadNum > 0 && needNum > 0) {
            need.setBagNum(need.getBagNum() + (hadNum > needNum ? needNum : hadNum));
            changed = true;
        }
        return changed;
    }

    /**
     * 获取订单列表，按预计的种植时间升序（不按订单号）
     * @return
     */
    private List<UserDrugChuFangOrderData> getOrderListByStartPlantTime(){
        List<UserDrugChuFangOrderData> tempList = new ArrayList<>(orderDataList);
        tempList.sort(new Comparator<UserDrugChuFangOrderData>() {
            @Override
            public int compare(UserDrugChuFangOrderData o1, UserDrugChuFangOrderData o2) {
                return (int)(o1.getDrugPlantStartTime() - o2.getDrugPlantStartTime());
            }
        });
        return tempList;
    }

    /**
     * 后台计算
     * @param enter 是否进入触发的计算
     */
    public void backendCal(boolean enter) {

        if (userDrugStoreData == null) {
            return;
        }

        //检查解锁
        if (!checkUnLock()) {
            return;
        }

        DrugAutoExecuteResult result = null;
        long offLineTime = 0L;
        long limitTime = DrugStoreMgr.getOffLineLimitTime();

        try {
            synchronized (userDrugStoreData) {
                if (isInView()) {
                    if (userDrugStoreData.getLastQuitViewTime() > 0) {
                        offLineTime = userDrugStoreData.getEntryViewTime() - userDrugStoreData.getLastQuitViewTime();
                        if(offLineTime > 1000) {
                            DrugStoreMgr.getLogger().debug("=={}, entryViewTime : {}, lastQuitViewTime :{}", player.getUserId(), DateHelper.getCurrentDateTimeString(userDrugStoreData.getEntryViewTime()),
                                    DateHelper.getCurrentDateTimeString(userDrugStoreData.getLastQuitViewTime()));
                        }
                    }
                    result = new DrugAutoExecuteResult(offLineTime);
                    userDrugStoreData.setLastQuitViewTime(userDrugStoreData.getEntryViewTime());
                } else {
                    return;
                }
                if(isOffLine(offLineTime, limitTime)) {
                    DrugStoreMgr.getLogger().debug("==={}离线时长：{}", player.getUserId(), offLineTime);
                }
                long offLineHandleNum = 0;
                //开启自动收获、自动领取订单（解锁补药师、解锁账房先生）后，生效
                if (isOffLine(offLineTime, limitTime) && isAutoOrderReward() && isAutoHarvest()) {
                    offLineHandleNum = offLineHandle(offLineTime - limitTime);
                }
                if(offLineHandleNum > 0){
                    DrugStoreMgr.getLogger().debug("=={}, 离线处理人数 : {}", player.getUserId(), offLineHandleNum);
                }
                //自动化
                boolean changed = true;
                while (changed) {
                    boolean innerChanged = false;
                    innerChanged = autoHarvest(result) || innerChanged;
                    innerChanged = orderFinish(result) || innerChanged;
                    innerChanged = orderNew(result) || innerChanged;
                    innerChanged = autoPlan(result) || innerChanged;
                    changed = innerChanged;
                }

            }
            //下发土地变更
            if (result.isLandStateChange()) {
                DrugStoreProto.DrugStoreLandDataSync.Builder syncMsg = getLandSyncBuilder();
                player.sendPacket(Protocol.U_DRUG_STORE_LAND_DATA_SYNC, syncMsg);
            }

            //完成订单
            int doneOrderNum = 0;

            //下发订单变化
            if (result.getOrderStateChangeMap().size() > 0) {
                DrugStoreProto.DrugStoreOrderChangeSync.Builder syncMsg = DrugStoreProto.DrugStoreOrderChangeSync.newBuilder();
                //按时间排序，每个桌子订单完成的数量不大于2，只保留一个完成的订单
                if(isOffLine(offLineTime, limitTime)){
                    List<UserDrugChuFangOrderData> orderDataList = new ArrayList<>();
                    for (Map.Entry<Long, UserDrugChuFangOrderData> entry : result.getOrderStateChangeMap().entrySet()) {
                        orderDataList.add(entry.getValue());
                    }
                    orderDataList.sort(new Comparator<UserDrugChuFangOrderData>() {
                        @Override
                        public int compare(UserDrugChuFangOrderData o1, UserDrugChuFangOrderData o2) {
                            return (int)(o2.getOrderTime() - o1.getOrderTime());
                        }
                    });
                    List<Integer> tableIdList = new ArrayList<>();
                    for (UserDrugChuFangOrderData orderData : orderDataList) {
                        if(orderData.getState() == 2){
                            doneOrderNum++;
                        }
                        //进入界面时，不下发已完成订单
                        if(enter && orderData.getState() == 2){
                            continue;
                        }
                        if(tableIdList.contains(orderData.getTable())){
                            continue;
                        }
                        syncMsg.addOrder(DrugStorePb.builderDrugOrderTemp(orderData));
                        if(orderData.getDrugMakeEndTime() > 0){
                            tableIdList.add(orderData.getTable());
                        }
                    }
                    //离线已完成订单
                    DrugStoreMgr.getLogger().debug("==={}离线已完成订单：{}", player.getUserId(), doneOrderNum);

                }else {
                    for (Map.Entry<Long, UserDrugChuFangOrderData> orderDataEntry : result.getOrderStateChangeMap().entrySet()) {
                        UserDrugChuFangOrderData orderData = orderDataEntry.getValue();
                        //进入界面时，不下发已完成订单
                        if(enter && orderData.getState() == 2){
                            continue;
                        }
                        syncMsg.addOrder(DrugStorePb.builderDrugOrderTemp(orderData));
                    }
                }
                //聚宝盆
                List<DrugOrderReward> rewards = new ArrayList<>(userDrugStoreData.getRewardList());
                for (DrugOrderReward orderReward : rewards) {
                    syncMsg.addBowlReward(DrugStorePb.buildTreasureBowlReward(orderReward));
                }
                for (int i = 0; i < userDrugStoreData.getNpcQueueList().size(); i++) {
                    DrugStoreQueue queue = userDrugStoreData.getNpcQueueList().get(i);
                    DrugStoreProto.DrugStoreQueueNpcTemp.Builder queueBuilder = DrugStorePb.buildDrugStoreQueueTemp(queue);
                    syncMsg.addWaitNpc(queueBuilder);
                }
                player.sendPacket(Protocol.U_DRUG_STORE_ORDER_SYNC, syncMsg);
            }
        } catch (Exception e) {
            DrugStoreMgr.getLogger().error(" backendCal error : playerId : {}, offLineSettleTime : {}", player.getUserId(), DateHelper.getCurrentDateTimeString(result.getOffLineTime()));
            DrugStoreMgr.getLogger().error("entryViewTime : {}, quitViewTime : {}", DateHelper.getCurrentDateTimeString(userDrugStoreData.getEntryViewTime()),
                    DateHelper.getCurrentDateTimeString(userDrugStoreData.getLastQuitViewTime()));
            DrugStoreMgr.getLogger().error(e.getMessage(), e);
        }

    }

    private boolean isOffLine(long offLineTime, long limitTime) {
        return offLineTime - limitTime > 0 && limitTime > 0;
    }

    /**
     * 离线处理：直接消耗n个病人
     */
    private long offLineHandle(long timeGap) {
        //待消耗n
        long toHandleNum = 0;
        synchronized (userDrugStoreData) {
            int queueNum = userDrugStoreData.getNpcQueueList().size();
            int secondPerPatient = DrugStoreMgr.getCuteTimePerPatientOffLine(queueNum);
            if (secondPerPatient >= 0) {
                if(secondPerPatient == 0){
                    toHandleNum = Integer.MAX_VALUE;
                }else {
                    toHandleNum = timeGap / (secondPerPatient * 1000);
                }
                toHandleNum = Math.min(toHandleNum, queueNum);
                if (toHandleNum > 0) {
                    DrugStoreMgr.getLogger().debug("--------------------离线处理：处理人员：{}", toHandleNum);
                    List<DrugStoreQueue> toHandleList = new ArrayList<>();

                    Iterator<DrugStoreQueue> iterator = userDrugStoreData.getNpcQueueList().iterator();
                    while (iterator.hasNext() && toHandleNum > 0) {
                        toHandleNum--;
                        toHandleList.add(iterator.next());
                        iterator.remove();
                    }
                    //
                    DrugStoreProto.DrugStoreShuLianDuSync.Builder shuLianDuSync = DrugStoreProto.DrugStoreShuLianDuSync.newBuilder();
//                    long totalExperience = 0L;
//                    long totalTongBi = 0L;
                    for (DrugStoreQueue queue : toHandleList) {
                        List<DrugOrderNeed> list = DrugStoreMgr.generateOrderDrugNeed(queue.getCf());
                        DrugOrderReward reward = calOrderReward(queue.getCf(), chuFangDataMap.get(queue.getCf()).getLv(), list, (int)(queue.getqT() / 1000));
//                        totalExperience += reward.getExp();
//                        totalTongBi += reward.getTb();

                        UserDrugChuFangData chuFangData = getChuFangDataMap().get(queue.getCf());
//                        if (chuFangData != null) {
//                            chuFangData.setShuLianDu(chuFangData.getShuLianDu() + reward.getSld());
//                            shuLianDuSync.addChuFang(DrugStorePb.buildDrugChuFangTemp(chuFangData));
//                        }
                        userDrugStoreData.getRewardList().add(reward);

                        Property logReward = new Property();
                        logReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(reward.getTb()));
                        logReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(reward.getExp()));
                        AutoLogMgr.add(new LogDrugStoreOrder(player.getUserId(), 0, new Date(), new Date(queue.getqT()), new Date(), chuFangData.getChuFang(), chuFangData.getLv(), 1, "",
                                PropertyHelper.parsePropertyToString(logReward)));
                    }

//                    userDrugStoreData.setTongBi(totalTongBi + userDrugStoreData.getTongBi());
//
//                    Property reward = new Property();
//                    reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(totalTongBi));
//                    reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(totalExperience));
//                    player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreOffLineReward);
//
//                    addActivityScoreRiseData((int) totalTongBi, 1);
//                    //冲榜
//                    player.notifyListener(eGamePlayerEventType.DrugStoreTongBiCrossUserRank.getValue(), new DrugStoreRankArgs(userDrugStoreData.getRankActivityDataMap()));
//                    player.notifyListener(eGamePlayerEventType.DrugStoreTongBiUserRank.getValue(), new DrugStoreRankArgs(userDrugStoreData.getRankActivityDataMap()));
//
//                    changeValueRank();
//                    player.sendChannelPacket(Protocol.U_DRUG_STORE_SHU_LIAN_DU_SYNC, shuLianDuSync);
                }
            }
        }
        return toHandleNum;
    }

    /**
     * 步骤1：自动收获；清空田地；
     *
     * @return 是否有变更
     */
    public boolean autoHarvest(DrugAutoExecuteResult result) {
        boolean changed = false;
        for (int i = 0; i < farmLandDataList.size(); i++) {
            UserDrugLandData landData = farmLandDataList.get(i);
            if (landData.getDrugId() == 0) {
                //未种植
                continue;
            }

            if (landData.getMatureTime() > result.getCurrentTimeMillis()) {
                //未成熟
                continue;
            }
            if (landData.getState() == 2 && isAutoHarvest()){
                result.setLandStateChange(true);
                changed = true;
                landData.setLastMatureTime(landData.getMatureTime());

                //日志
                AutoLogMgr.add(new LogDrugStorePlant(player.getUserId(), landData.getLandId(), landData.getDrugId(), 1, new Date(landData.getPlantTime()), new Date(landData.getMatureTime())));

                handleLandHarvest(landData);
                //logger.debug("landId:{} itemId:{}, 自动补药完成, 最后成熟时间 {}", landData.getLandId(), landData.getDrugId(), DateHelper.getCurrentDateTimeString(landData.getLastMatureTime()));
                continue;
            }
            if (landData.getState() == 2){
                continue;
            }
            landData.setLastMatureTime(landData.getMatureTime());
            landData.setState(2);

            result.setLandStateChange(true);
            changed = true;
            //logger.debug("landId:{} itemId:{}, 成熟了，种植时间：{}， 成熟时间：{}, 种植Id:{}", landData.getLandId(), landData.getDrugId(),
                    //DateHelper.getCurrentDateTimeString(landData.getPlantTime()), DateHelper.getCurrentDateTimeString(landData.getMatureTime()), landData.getPlanId());
            if (!isAutoHarvest()) {
                continue;
            }

            //日志
            AutoLogMgr.add(new LogDrugStorePlant(player.getUserId(), landData.getLandId(), landData.getDrugId(), 2, new Date(landData.getPlantTime()), new Date(landData.getMatureTime())));

            //logger.debug("landId:{} itemId:{}, 自动补药完成, 最后成熟时间 {}", landData.getLandId(), landData.getDrugId(), DateHelper.getCurrentDateTimeString(landData.getLastMatureTime()));
            handleLandHarvest(landData);
        }
        return changed;
    }

    /**
     * 步骤2：订单处理（完成：空桌子）
     *
     * @return 是否有变更
     */
    public boolean orderFinish(DrugAutoExecuteResult result) {
        boolean changed = false;
        List<UserDrugChuFangOrderData> orderList = getOrderListByStartPlantTime();
        for (int i = 0; i < orderList.size(); i++) {
            UserDrugChuFangOrderData orderData = orderList.get(i);
            if (orderData.isNeedSync()) {
                changed = true;
                result.getOrderStateChangeMap().put(orderData.getNo(), orderData);
                orderData.setNeedSync(false);
            }
            int chuFangLv = chuFangDataMap.get(orderData.getChuFang()).getLv();
            if (orderData.getState() > 0) {
                if (orderData.getState() == 1 && isAutoOrderReward()) {
                    //logger.debug("orderId:{}, 自动领奖到聚宝盆", orderData.getNo());
                    orderData.setState(2);
                    int rewardTime = (int)(orderData.getReceiveTime() == 0 ? orderData.getOrderTime() /1000 : orderData.getReceiveTime() /1000);
                    DrugOrderReward reward = calOrderReward(orderData.getChuFang(), chuFangLv, orderData.getProcess(), rewardTime);
                    orderData.setGetReward(true);
                    orderData.setChuFangLv(chuFangLv);
                    orderData.setGetRewardTime(result.getCurrentTimeMillis());

                    Property orderReward = new Property();
                    orderReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(reward.getExp()));
                    orderReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(reward.getTb()));
                    orderData.setReward(PropertyHelper.parsePropertyToString(orderReward));

                    userDrugStoreData.getRewardList().add(reward);

                    //日志
                    AutoLogMgr.add(new LogDrugStoreOrder(player.getUserId(), orderData.getNo(), new Date(orderData.getOrderTime()), new Date(orderData.getReceiveTime() == 0 ? orderData.getOrderTime() : orderData.getReceiveTime()),
                            new Date(orderData.getFinishTime()), orderData.getChuFang(), chuFangLv, 1, "",
                            PropertyHelper.parsePropertyToString(orderReward)));

                    updateTableLastDoneTime(orderData.getTable(), orderData.getGetRewardTime());
                    changed = true;
                    result.getOrderStateChangeMap().put(orderData.getNo(), orderData);
                }
                continue;
            }
            //计算订单完成时间
            long lastTime = 0L;
            //计算订单是否完成
            int doneDrugNum = 0;
            calAutoBagToOrderNeed(orderData);
            for (DrugOrderNeed process : orderData.getProcess()) {
                if (process.getEndTime() > lastTime) {
                    lastTime = process.getEndTime();
                }
                if (process.getPlanNum() + process.getBagNum() == process.getNeedNum()) {
                    doneDrugNum++;
                }
            }

            if (doneDrugNum != orderData.getProcess().size()) {
                continue;
            }
            if(orderData.getDrugPlantDoneTime() == 0){
                if(lastTime == 0){
                    //直接从背包满足的，结束时间等于开始种植时间
                    lastTime = orderData.getDrugPlantStartTime();
                }
                //logger.debug("orderId:{}, 结束抓药，时间：{}", orderData.getNo(), DateHelper.getCurrentDateTimeString(lastTime));
                orderData.setDrugPlantDoneTime(Math.max(lastTime, orderData.getOrderTime()));
            }
            if (orderData.getDrugMakeEndTime() == 0) {
                orderData.setDrugMakeEndTime(orderData.getDrugPlantDoneTime() + GameConfig.DRUGSTORE_ANI_TIME_MAKE);
            }
            if (orderData.getDrugMakeEndTime() <= result.getCurrentTimeMillis()) {
                orderData.setState(1);
                //logger.debug("orderId:{}, 结束制药，时间：{}", orderData.getNo(), DateHelper.getCurrentDateTimeString(orderData.getDrugMakeEndTime()));
                //订单完成，扣扣背包
                for (DrugOrderNeed process : orderData.getProcess()) {
                    if (!process.isDeduct()) {
                        if (process.getBagNum() > 0) {
                            userDrugStoreData.subDrugNum(process.getItemId(), process.getBagNum());
                        }
                        process.setDeduct(true);
                    }
                }
                orderData.setFinishTime(orderData.getDrugMakeEndTime());
            }else {
                //制药未结束
                continue;
            }

            changed = true;
            result.getOrderStateChangeMap().put(orderData.getNo(), orderData);

            if (!isAutoOrderReward()) {
                continue;
            }
            //logger.debug("orderId:{}, 自动领奖到聚宝盆【正】", orderData.getNo());
            //自动领奖到聚宝盆
            orderData.setState(2);
            int rewardTime = (int)(orderData.getReceiveTime() == 0 ? orderData.getOrderTime() /1000 : orderData.getReceiveTime() /1000);
            DrugOrderReward reward = calOrderReward(orderData.getChuFang(), chuFangLv, orderData.getProcess(), rewardTime);
            orderData.setGetReward(true);
            orderData.setChuFangLv(chuFangLv);
            orderData.setGetRewardTime(orderData.getFinishTime());

            Property orderReward = new Property();
            orderReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(reward.getExp()));
            orderReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(reward.getTb()));
            orderData.setReward(PropertyHelper.parsePropertyToString(orderReward));

            UserDrugChuFangData chuFangData = getPrescription(orderData.getChuFang());
            if (chuFangData != null) {
                reward.setLv(chuFangData.getLv());
                orderData.setChuFangLv(chuFangData.getLv());
            }

            userDrugStoreData.getRewardList().add(reward);

            //日志
            AutoLogMgr.add(new LogDrugStoreOrder(player.getUserId(), orderData.getNo(), new Date(orderData.getOrderTime()), new Date(orderData.getReceiveTime()), new Date(orderData.getFinishTime()), orderData.getChuFang(), chuFangLv, 1, "",
                    PropertyHelper.parsePropertyToString(orderReward)));

            //更新诊桌的最后诊疗完成时间
            updateTableLastDoneTime(orderData.getTable(), orderData.getGetRewardTime());
        }
        return changed;
    }

    /**
     * 步骤2：订单处理（生成：占桌子，接治病人）；
     */
    public boolean orderNew(DrugAutoExecuteResult result) {
        boolean changed = false;
        Iterator<UserDrugChuFangOrderData> iterator = orderDataList.iterator();
        while (iterator.hasNext()) {
            UserDrugChuFangOrderData orderData = iterator.next();
            if (orderData.isGetReward() && !orderData.isDirty()) {
                iterator.remove();
                doneOrderDataList.add(orderData);
            }
        }
        //空闲桌子编号
        List<Integer> tableIdList = new ArrayList<>();
        for (int i = 0; i < orderDataList.size(); i++) {
            UserDrugChuFangOrderData orderData = orderDataList.get(i);
            if(orderData.getState() == 2){
                continue;
            }
            tableIdList.add(orderData.getTable());
        }
        int tableSize = userDrugStoreData.getDoctorTableList().size();
        for (int i = 0; i < tableSize; i++) {
            int tableId = i + 1;
            if (tableIdList.contains(tableId)) {
                continue;
            }
            long lastCuredTime = getDrugTableLastCuteTime(tableId);
            //空桌子，消耗队列
            if (userDrugStoreData.getNpcQueueList().size() > 0) {
                DrugStoreQueue queue = userDrugStoreData.getNpcQueueList().remove(0);
                UserDrugChuFangOrderData newOrderData = new UserDrugChuFangOrderData();
                newOrderData.setInsertOption();
                newOrderData.setUserId(player.getUserId());
                userDrugStoreData.setOrderNo(1 + userDrugStoreData.getOrderNo());
                newOrderData.setNo(userDrugStoreData.getOrderNo());
                newOrderData.setNpc(queue.getqId());
                newOrderData.setTable(tableId);
                newOrderData.setChuFang(queue.getCf());
                newOrderData.setDialogId(queue.getdId());
                //处方的药材需求
                List<DrugOrderNeed> needList = DrugStoreMgr.generateOrderDrugNeed(newOrderData.getChuFang());
                newOrderData.setProcess(needList);
                //计算背包剩余药材
                calAutoBagToOrderNeed(newOrderData);

                //订单时间不能早于接待时间和诊桌最后诊疗时间
                newOrderData.setOrderTime(Math.max(queue.getqT(), result.getOffLineStartSettleTime(lastCuredTime)));
                newOrderData.setReceiveTime(queue.getqT());
                //这个是预期，
                newOrderData.setDrugPlantStartTime(newOrderData.getOrderTime() + GameConfig.DRUGSTORE_ANI_TIME_DIALOGUE + DrugStoreMgr.getWalkTimeToDrugTable(tableId));
                //
                //DrugStoreMgr.getLogger().debug("orderNo:{}, 订单时间：{}, 预期种植开始时间 ：{}", newOrderData.getNo(), DateHelper.getCurrentDateTimeString(newOrderData.getOrderTime()),
                        //DateHelper.getCurrentDateTimeString(newOrderData.getDrugPlantStartTime()));
                orderDataList.add(newOrderData);
                changed = true;
                result.getOrderStateChangeMap().put(newOrderData.getNo(), newOrderData);
            }
        }
        return changed;
    }

    /**
     * 步骤4：自动种植：占田地
     */
    public boolean autoPlan(DrugAutoExecuteResult result) {
        if(!isAutoHarvest()){
            return false;
        }
        boolean changed = false;
        boolean canPlan = true;
        List<UserDrugChuFangOrderData> orderList = getOrderListByStartPlantTime();
        for (int i = 0; i < orderList.size(); i++) {
            UserDrugChuFangOrderData orderData = orderList.get(i);
            if (orderData.getState() != 0) {
                continue;
            }
            if (!canPlan) {
                break;
            }
            //计算背包剩余药材
            calAutoBagToOrderNeed(orderData);
            for (DrugOrderNeed process : orderData.getProcess()) {
                if (!canPlan) {
                    break;
                }
                while (process.getPlanNum() + process.getBagNum() + process.getPlaningNum() < process.getNeedNum()) {
                    //获取空闲田地
                    UserDrugLandData landData = getCanPlantLandData();
                    if (landData == null) {
                        canPlan = false;
                        break;
                    }
                    //种植时间，不能早于订单生成+动画的时间和田地的最后成熟时间;
                    long plantTime = Math.max(orderData.getDrugPlantStartTime(), result.getOffLineStartSettleTime(landData.getLastMatureTime()));
                    if(plantTime > result.getCurrentTimeMillis()){
                        //未到种植时间，不可种植
                        break;
                    }
                    //DrugStoreMgr.getLogger().debug("自动种植，landId:{}, 最后成熟时间：{}", landData.getLandId(), DateHelper.getCurrentDateTimeString(landData.getLastMatureTime()));
                    if(orderData.getDrugPlantStartTime() == 0){
                        orderData.setDrugPlantStartTime(plantTime);
                    }
                    landData.setState(1);
                    landData.setPlantTime(plantTime);
                    landData.setMatureTime(landData.getPlantTime() + GameConfig.DRUGSTORE_ANI_TIME_GROW_UP);
                    landData.setOrderNo(orderData.getNo());
                    userDrugStoreData.setPlantId(1 + userDrugStoreData.getPlantId());
                    landData.setPlanId(userDrugStoreData.getPlantId());
                    landData.setDrugId(process.getItemId());
                    process.setPlaningNum(1 + process.getPlaningNum());
                    orderData.setUpdateOption();
                    orderData.setNeedSync(true);
                    //logger.debug("orderNo:{}, 自动种植， langId:{}, 种植时间：{}， 成熟时间：{}， 种植ID:{}", orderData.getNo(), landData.getLandId(),
                            //DateHelper.getCurrentDateTimeString(landData.getPlantTime()), DateHelper.getCurrentDateTimeString(landData.getMatureTime()), landData.getPlanId());
                    changed = true;
                    result.setLandStateChange(true);
                }
            }
        }
        return changed;
    }

    /**
     * 获取空闲田地
     */
    public UserDrugLandData getCanPlantLandData() {
        for (int i = 0; i < farmLandDataList.size(); i++) {
            UserDrugLandData landData = farmLandDataList.get(i);
            if (landData.getState() == 0) {
                return landData;
            }
        }
        return null;
    }

    /**
     * 重置种植数据
     */
    private void clearLandData(UserDrugLandData landData) {
        landData.setDrugId(0);
        landData.setMatureTime(0);
        landData.setPlanId(0);
        landData.setOrderNo(0);
        landData.setState(0);
        landData.setPlantTime(0);
    }

    /**
     * 更新诊桌最后诊疗完成/空闲时间
     */
    private void updateTableLastDoneTime(int table, long getRewardTime) {
        for (int i = 0; i < userDrugStoreData.getDoctorTableList().size(); i++) {
            DrugStoreDoctorTable doctorTable = userDrugStoreData.getDoctorTableList().get(i);
            if (doctorTable.getTableId() == table) {
                doctorTable.setLastCuredTime(getRewardTime);
                //logger.debug("更新诊桌[{}], 最后诊疗时间：{}", table, DateHelper.getCurrentDateTimeString(getRewardTime));
                userDrugStoreData.setUpdateOption();
                break;
            }
        }
    }

    /**
     * 自动种植（交付给订单）
     */
    private void supplyOrderDrug(UserDrugLandData landData, UserDrugChuFangOrderData orderData) {
        DrugOrderNeed target = null;
        for (DrugOrderNeed process : orderData.getProcess()) {
            if (process.getItemId() == landData.getDrugId()) {
                target = process;
            }
        }
        if (target == null) {
            return;
        }
        target.setPlanId(landData.getPlanId());
        target.setPlanNum(1 + target.getPlanNum());
        target.setEndTime(landData.getLastMatureTime());
        target.setPlaningNum(target.getPlaningNum() - 1);
        orderData.setNeedSync(true);
        orderData.setUpdateOption();

        //日志
        AutoLogMgr.add(new LogDrugStoreDrug(player.getUserId(), landData.getDrugId(), 2, 1, 1, target.getPlanNum(), orderData.getNo(), new Date(landData.getMatureTime())));
    }

    /**
     * 手动种植
     */
    public int manualPlant(int landId, int drugId) {

        //检查解锁
        if (!checkUnLock()) {
            return GameErrorCode.E_DRUG_STORE_CONDITION_IS_LOCK;
        }

        UserDrugLandData landData = getFarmLandData(landId);
        if (landData == null) {
            return GameErrorCode.E_DRUG_STORE_LAND_LOCK;
        }

        synchronized (userDrugStoreData) {
            if (landData.getDrugId() > 0) {
                return GameErrorCode.E_DRUG_STORE_LAND_PLANED;
            }
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(drugId);
            if(goodsInfo == null){
                return GameErrorCode.E_GOODS_NO_EXIST;
            }
            //成熟时间
            long time = GameConfig.DRUGSTORE_ANI_TIME_GROW_UP;

            landData.setDrugId(drugId);
            landData.setPlantTime(System.currentTimeMillis());
            landData.setMatureTime(time + landData.getPlantTime());
            landData.setState(1);

            backendCal(false);
        }
        DrugStoreProto.DrugPlantRespMsg.Builder builder = DrugStoreProto.DrugPlantRespMsg.newBuilder().setRet(0);
        builder.setLand(DrugStorePb.buildDrugLandTemp(landData));
        player.sendPacket(Protocol.U_DRUG_STORE_PLANT_DRUG, builder);

        //下发土地数据
        DrugStoreProto.DrugStoreLandDataSync.Builder syncMsg = getLandSyncBuilder();
        player.sendPacket(Protocol.U_DRUG_STORE_LAND_DATA_SYNC, syncMsg);

        return 0;
    }

    /**
     * 处方升级
     */
    public int upgradeChuFang(int chuFang) {

        DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(chuFang);
        if (prescriptionInfo == null) {
            return GameErrorCode.E_DRUG_STORE_CHU_FANG_CONFIG_EXIST;
        }
        UserDrugChuFangData chuFangData = getChuFangDataMap().get(chuFang);
        if (chuFangData == null) {
            return GameErrorCode.E_DRUG_STORE_CHU_FANG_UNLOCK;
        }

        DrugStoreDrugUpgradeInfo upgradeInfo = DrugStoreConfigMgr.getDrugStoreDrugUpgradeInfo(chuFang, chuFangData.getLv());
        if (upgradeInfo == null || upgradeInfo.getNeed() == 0) {
            return GameErrorCode.E_DRUG_STORE_CHU_FANG_LEVEL_TOP;
        }

        if(chuFangData.getShuLianDu() < upgradeInfo.getNeed()){
            return GameErrorCode.E_DRUG_STORE_SHULIANDU_NO_ENOUGH;
        }

        chuFangData.setLv(1 + chuFangData.getLv());
        notifyDrugStoreChuFangLevel();

        //日志
        AutoLogMgr.add(new LogDrugStoreUpgrade(player.getUserId(), 3, chuFang, chuFangData.getLv() - 1, chuFangData.getLv(), ""));

        DrugStoreProto.DrugStoreChuFangUpgradeRespMsg.Builder respMsg = DrugStoreProto.DrugStoreChuFangUpgradeRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setChuFang(DrugStorePb.buildDrugChuFangTemp(chuFangData));
        player.sendPacket(Protocol.U_DRUG_STORE_CHU_FANG_UPGRADE, respMsg);

        return 0;
    }

    /**
     * 处方升级(一键升级所有到最高)
     */
    public int upgradeChuFangOneKey() {

        DrugStoreProto.DrugStoreChuFangUpgradeOneKeyRespMsg.Builder respMsg = DrugStoreProto.DrugStoreChuFangUpgradeOneKeyRespMsg.newBuilder();
        respMsg.setRet(0);
        for (Map.Entry<Integer, UserDrugChuFangData> dataEntry : getChuFangDataMap().entrySet()) {
            UserDrugChuFangData chuFangData = dataEntry.getValue();
            int oldLv = chuFangData.getLv();
            int addLv = 0;
            for (int i = 0; i < 1000; i++) {
                DrugStoreDrugUpgradeInfo upgradeInfo = DrugStoreConfigMgr.getDrugStoreDrugUpgradeInfo(chuFangData.getChuFang(), oldLv + i);
                if (upgradeInfo == null || upgradeInfo.getNeed() == 0) {
                    break;
                }
                if(chuFangData.getShuLianDu() < upgradeInfo.getNeed()){
                    break;
                }
                addLv++;
            }

            if(addLv > 0){
                //日志
                AutoLogMgr.add(new LogDrugStoreUpgrade(player.getUserId(), 3, chuFangData.getChuFang(), chuFangData.getLv(), chuFangData.getLv() + addLv, ""));

                chuFangData.setLv(addLv + chuFangData.getLv());

                respMsg.addChuFang(DrugStorePb.buildDrugChuFangTemp(chuFangData));
            }
        }

        if(respMsg.getChuFangCount() > 0){
            notifyDrugStoreChuFangLevel();
        }else {
            respMsg.setRet(GameErrorCode.E_DRUG_STORE_SHULIANDU_NO_ENOUGH);
        }

        player.sendPacket(Protocol.U_DRUG_STORE_CHU_FANG_UPGRADE_ONE_KEY, respMsg);

        return 0;
    }

    /**
     * 药铺升级
     */
    public int storeUpgrade() {

        DrugStoreBadgeInfo badgeInfo = DrugStoreConfigMgr.getDrugStoreBadgeInfo(userDrugStoreData.getDrugStoreLv());
        if (badgeInfo == null) {
            return GameErrorCode.E_DRUG_STORE_CONFIG_NOT_EXIST;
        }
        if (badgeInfo.getUnlockValue() <= 0){
            return GameErrorCode.E_DRUG_STORE_LEVEL_TOP;
        }

        if (userDrugStoreData.getExperience() < badgeInfo.getUnlockValue()) {
            return GameErrorCode.E_DRUG_STORE_EXPERIENCE_NO_ENOUGH;
        }
        userDrugStoreData.setDrugStoreLv(1 + userDrugStoreData.getDrugStoreLv());
        DrugStoreProto.UpgradeDrugStoreRespMsg.Builder respMsg = DrugStoreProto.UpgradeDrugStoreRespMsg.newBuilder();
        //升级效果
        DrugStoreBadgeInfo newBadgeInfo = DrugStoreConfigMgr.getDrugStoreBadgeInfo(userDrugStoreData.getDrugStoreLv());
        if (newBadgeInfo != null) {
            //解锁补药师、账房先生
            synchronized (userDrugStoreData) {
                boolean unLock = unLockAdminNpc();
                if (unLock) {
                    //更新土地的最后成熟时间
                    for (int i = 0; i < farmLandDataList.size(); i++) {
                        UserDrugLandData landData = farmLandDataList.get(i);
                        long currentTimeMillis = System.currentTimeMillis();
                        //纠正自动化开启后，土地的可用起始时间
                        if(landData.getMatureTime() < currentTimeMillis && landData.getLastMatureTime() < currentTimeMillis) {
                            landData.setMatureTime(currentTimeMillis);
                            landData.setLastMatureTime(currentTimeMillis);
                        }
                    }
                }
                respMsg.setUnLock(unLock);
            }
            // 更新徽章
            updateBadge();
        }
        unLockDrug();
        unLockChuFang();
        respMsg.setRet(0);
        List<Integer> newDrugList = DrugStoreMgr.getUnLockDrug(userDrugStoreData.getDrugStoreLv());
        respMsg.addAllDrug(newDrugList);

        List<DrugStorePrescriptionInfo> chuFangList = DrugStoreConfigMgr.getUnLock(userDrugStoreData.getDrugStoreLv());
        for (DrugStorePrescriptionInfo info : chuFangList) {
            respMsg.addChuFang(info.getId());
        }
        if (chuFangList.size() > 0) {
            //重新刷下队列
            synchronized (userDrugStoreData) {
                for (int i = 0; i < userDrugStoreData.getNpcQueueList().size(); i++) {
                    if (i > 4) {
                        DrugStoreQueue queue = userDrugStoreData.getNpcQueueList().get(i);
                        DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.randomUnLockChuFang(userDrugStoreData.getDrugStoreLv());
                        if (prescriptionInfo != null) {
                            queue.setCf(prescriptionInfo.getId());
                            List<Integer> dialogList = StringUtils.stringToIntegerList(prescriptionInfo.getDialoguePeople(), "\\|");
                            //随机对话
                            queue.setdId(new Random().nextInt(dialogList.size()));
                            userDrugStoreData.setUpdateOption();
                        }
                    }
                }
            }

        }
        //日志
        AutoLogMgr.add(new LogDrugStoreUpgrade(player.getUserId(), 1, 0, userDrugStoreData.getDrugStoreLv() - 1, userDrugStoreData.getDrugStoreLv(), ""));

        respMsg.setStoreLv(userDrugStoreData.getDrugStoreLv());
        player.sendPacket(Protocol.U_DRUG_STORE_UPGRADE, respMsg);

        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        return 0;
    }

    /**
     * 工艺升级
     */
    public int upgradeTech(int tech) {
        DrugStoreTeach drugStoreTeach = null;
        for (DrugStoreTeach teach : userDrugStoreData.getTechList()) {
            if(teach.getId() == tech){
                drugStoreTeach = teach;
            }
        }
        if(drugStoreTeach == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        DrugStoreDrugUpgradeInfo upgradeInfo = DrugStoreConfigMgr.getDrugStoreDrugUpgradeInfo(tech, drugStoreTeach.getLv());
        if (upgradeInfo == null || upgradeInfo.getNeed() == 0) {
            return GameErrorCode.E_DRUG_STORE_TECH_LEVEL_TOP;
        }

        String consume = PropertyHelper.parseGoodsToString(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(upgradeInfo.getNeed()));
        if (!player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(consume), eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreTechUpgradeConsume)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        drugStoreTeach.setLv(1 + drugStoreTeach.getLv());
        userDrugStoreData.setUpdateOption();
        notifyDrugStoreTechLevel();

        //日志
        AutoLogMgr.add(new LogDrugStoreUpgrade(player.getUserId(), 2, tech, drugStoreTeach.getLv() - 1, drugStoreTeach.getLv(), consume));

        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        player.sendPacket(Protocol.U_DRUG_STORE_TEACH_UPGRADE, DrugStoreProto.UpgradeDrugTeachRespMsg.newBuilder().setRet(0));
        return 0;
    }

    /**
     * 工艺升级(同步升级)
     */
    public int upgradeTechOneKey() {

        DrugStoreProto.UpgradeDrugTeachOneKeyRespMsg.Builder clientMsg = DrugStoreProto.UpgradeDrugTeachOneKeyRespMsg.newBuilder();
        clientMsg.setRet(0);

        //计算所有消耗
        Property allCost = new Property();

        Map<Integer, Property> consumeList = new HashMap<>();

        for (DrugStoreTeach teach : userDrugStoreData.getTechList()) {

            DrugStoreDrugUpgradeInfo upgradeInfo = DrugStoreConfigMgr.getDrugStoreDrugUpgradeInfo(teach.getId(), teach.getLv());
            if (upgradeInfo == null || upgradeInfo.getNeed() == 0) {
                continue;
            }
            String consume = PropertyHelper.parseGoodsToString(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(upgradeInfo.getNeed()));
            Property property = PropertyHelper.parseStringToProperty(consume);
            allCost.addProperty(property);
            consumeList.put(teach.getId(), property);

        }

        if(allCost.isNothing()){
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        if (!player.getModule(CurrencyModule.class).removeCurrency(allCost, eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreTechUpgradeSyncConsume)) {

            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;

        }else {

            for (DrugStoreTeach teach : userDrugStoreData.getTechList()) {
                if(!consumeList.containsKey(teach.getId())){
                    continue;
                }

                //日志
                AutoLogMgr.add(new LogDrugStoreUpgrade(player.getUserId(), 2, teach.getId(), teach.getLv() - 1, teach.getLv(),
                        PropertyHelper.parsePropertyToString(consumeList.get(teach.getId()))));

                teach.setLv(1 + teach.getLv());
                userDrugStoreData.setUpdateOption();

                clientMsg.addTech(DrugStorePb.buildTech(teach));
            }

            notifyDrugStoreTechLevel();


            player.getModule(EarnSpeedModule.class).scheduleAddSilver();

            player.sendPacket(Protocol.U_DRUG_STORE_TEACH_UPGRADE_ONE_KEY, clientMsg);

        }

        return 0;
    }

    /**
     * 解锁自动npc(补药师、账房先生)
     */
    private boolean unLockAdminNpc() {
        boolean unLock = false;
        for (int npcId : DrugStoreConfigMgr.getBadgeInfoSpecialEffect(userDrugStoreData.getDrugStoreLv(), 3)) {
            if (npcId == 1) {
                userDrugStoreData.setDruggistLv(1);
                unLock = true;
            } else if (npcId == 2) {
                userDrugStoreData.setBookKeeperLv(1);
                unLock = true;
            }

            //日志
            AutoLogMgr.add(new LogDrugStoreUnLock(player.getUserId(), 4, npcId));
        }
        return unLock;
    }

    /**
     * 解锁诊桌
     */
    public int unlockDoctorTable(int tableId) {

        if (getDrugStoreDoctorTable(tableId) == null) {
            DrugStoreDoctorTable table = new DrugStoreDoctorTable();
            table.setTableId(tableId);
            table.setDoctorId(tableId);
            table.setLastCuredTime(System.currentTimeMillis());
            userDrugStoreData.getDoctorTableList().add(table);

            //日志
            AutoLogMgr.add(new LogDrugStoreUnLock(player.getUserId(), 2, tableId));
        }

        DrugStoreProto.UnlockDrugDoctorTableRespMsg.Builder respMsg = DrugStoreProto.UnlockDrugDoctorTableRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setNum(userDrugStoreData.getDoctorTableList().size());
        player.sendPacket(Protocol.U_DRUG_STORE_DOCTOR_TABLE_UNLOCK, respMsg);
        return 0;
    }

    /**
     * 开垦田地
     */
    public int unlockLandData(int landId) {

        if (getFarmLandData(landId) != null) {
            return GameErrorCode.E_DRUG_STORE_LAND_UNLOCK;
        }
        UserDrugLandData landData = new UserDrugLandData();
        landData.setUserId(player.getUserId());
        landData.setLandId(landId);
        landData.setInsertOption();
        landData.setLastMatureTime(System.currentTimeMillis());
        farmLandDataList.add(landData);

        userDrugStoreData.setLandNum(farmLandDataList.size());

        //日志
        AutoLogMgr.add(new LogDrugStoreUnLock(player.getUserId(), 1, landId));

        DrugStoreProto.UnlockDrugLandRespMsg.Builder respMsg = DrugStoreProto.UnlockDrugLandRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setNum(farmLandDataList.size());
        respMsg.setLand(DrugStorePb.buildDrugLandTemp(landData));
        player.sendPacket(Protocol.U_DRUG_STORE_LAND_UNLOCK, respMsg);
        return 0;
    }

    /**
     * 接待检查
     * @param assistantFlag 是否是小玉助手
     * @return
     */
    public int receptCheck(boolean assistantFlag) {

        recoverUserEnergyPower();

        //检查解锁
        if (!checkUnLock()) {
            return GameErrorCode.E_DRUG_STORE_CONDITION_IS_LOCK;
        }

        //病人存量不足
        if (userDrugStoreData.getPower() <= 0) {
            if (!assistantFlag) {
                player.notifyListener(eGamePlayerEventType.RechargeDrugStore.getValue(), 0);
                player.notifyListener(eGamePlayerEventType.RechargeDrugStoreNew.getValue(), 0);
            }
            return GameErrorCode.E_DRUG_STORE_PATIENT_NUM_NO_ENOUGH;
        }

        //接待人数达到上限
        if (userDrugStoreData.getNpcQueueList().size() >= GameConfig.DRUGSTORE_WAIT_MAX_NUM) {
            return GameErrorCode.E_DRUG_STORE_RECEPTION_LIMIT;
        }

        return 0;
    }

    /**
     * 检查初始化解锁
     *
     * @return
     */
    public boolean checkUnLock() {

        if (userDrugStoreData == null) {
            return false;
        }

        return userDrugStoreData.getDoctorTableList().size() > 0 && getFarmLandDataList().size() > 0
                && getChuFangDataMap().size() > 0;
    }

    /**
     * 计算背包药材库存，扣掉已预分配给订单的数量
     */
    private Map<Integer, Integer> calBagStock() {
        //已分配数量
        Map<Integer, Integer> preUsedMap = new HashMap<>();
        for (int i = 0; i < orderDataList.size(); i++) {
            UserDrugChuFangOrderData orderData = orderDataList.get(i);
            for (DrugOrderNeed process : orderData.getProcess()) {
                if (process.getBagNum() > 0 && !process.isDeduct()) {
                    int oldNum = preUsedMap.getOrDefault(process.getItemId(), 0);
                    preUsedMap.put(process.getItemId(), oldNum + process.getBagNum());
                }
            }
        }
        //剩余数量
        Map<Integer, Integer> resultMap = new HashMap<>();
        //遍历背包
        for (Map.Entry<Integer, Integer> entry : userDrugStoreData.getDrugNumMap().entrySet()) {
            int usedNum = preUsedMap.getOrDefault(entry.getKey(), 0);
            resultMap.put(entry.getKey(), entry.getValue() - usedNum);
        }
        return resultMap;
    }

    /**
     * 进入界面
     */
    public void entryView(long entryViewTime) {
        if(userDrugStoreData == null){
            return;
        }
        synchronized (userDrugStoreData) {
            userDrugStoreData.setEntryViewTime(entryViewTime);
            backendCal(true);
        }
    }

    /**
     * 退出界面
     */
    public void quitView(long time){
        if(userDrugStoreData != null){
            synchronized (userDrugStoreData) {
                userDrugStoreData.setLastQuitViewTime(time);
            }
        }
    }

    /**
     * 是否解锁自动领取订单奖励
     */
    public boolean isAutoOrderReward() {
        return userDrugStoreData.getBookKeeperLv() > 0;
    }

    /**
     * 是否解锁自动收获
     */
    public boolean isAutoHarvest() {
        return userDrugStoreData.getDruggistLv() > 0;
    }

    /**
     * 玩家是否在界面
     */
    public boolean isInView() {
        return userDrugStoreData.getEntryViewTime() >= userDrugStoreData.getLastQuitViewTime() && userDrugStoreData.getEntryViewTime() > 0;
    }

    /**
     * 获取未完成订单
     */
    private UserDrugChuFangOrderData getUserDrugChuFangOrderData(long orderNo) {
        for (int i = 0; i < orderDataList.size(); i++) {
            UserDrugChuFangOrderData orderData = orderDataList.get(i);
            if (orderData.getNo() == orderNo) {
                return orderData;
            }
        }
        return null;
    }

    /**
     * 随机已解锁处方(没有权重)
     */
    public UserDrugChuFangData randomPrescription() {
        List<UserDrugChuFangData> list = new ArrayList<>();
        for (Map.Entry<Integer, UserDrugChuFangData> infoEntry : chuFangDataMap.entrySet()) {
            list.add(infoEntry.getValue());
        }
        if (list.size() == 0) {
            return null;
        }
        int idx = new Random().nextInt(list.size());
        return list.get(idx);
    }

    /**
     * 获取已解锁处方
     */
    public UserDrugChuFangData getPrescription(int chuFang) {
        return chuFangDataMap.get(chuFang);
    }

    /**
     * 获取诊桌的最后诊疗时间
     */
    public long getDrugTableLastCuteTime(int tableId) {
        DrugStoreDoctorTable table = getDrugStoreDoctorTable(tableId);
        if (table == null) {
            return 0L;
        }
        return table.getLastCuredTime();
    }

    public DrugStoreDoctorTable getDrugStoreDoctorTable(int tableId) {
        for (int i = 0; i < userDrugStoreData.getDoctorTableList().size(); i++) {
            DrugStoreDoctorTable table = userDrugStoreData.getDoctorTableList().get(i);
            if (table.getTableId() == tableId) {
                return table;
            }
        }
        return null;
    }

    /**
     * 获取田地
     */
    private UserDrugLandData getFarmLandData(int landId) {
        for (int i = 0; i < farmLandDataList.size(); i++) {
            UserDrugLandData landData = farmLandDataList.get(i);
            if (landData.getLandId() == landId) {
                return landData;
            }
        }
        return null;
    }

    /**
     * 精进技能上限加成
     *
     * @return
     */
    public int getStageSkillMaxLevelAdd() {
        int addLv = 0;
        if (userDrugStoreData == null) {
            return addLv;
        }
        DrugStoreBadgeInfo badgeInfo = DrugStoreConfigMgr.getDrugStoreBadgeInfo(userDrugStoreData.getDrugStoreLv());
        if (badgeInfo != null) {
            for (int skillId : badgeInfo.getSkillsList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo != null && skillInfo.getType() == eSkillType.DrugStorePatronsStageLvLimitSkill.getValue()) {
                    addLv += SkillMgr.getSkillAddition(skillInfo, userDrugStoreData.getDrugStoreLv());
                }
            }
        }
        return addLv;
    }

    /**
     * 疑难杂症BUFF
     */
    public void addYNZZBuff(int buffValue, long endTime){
        if(userDrugStoreData == null){
            return;
        }
        DrugStoreBuffValue drugStoreBuffValue = new DrugStoreBuffValue(buffValue, endTime);
        userDrugStoreData.setBuffValue(drugStoreBuffValue);
        syncStoreBuffValue();
    }

    public UserDrugStoreData getUserDrugStoreData() {
        return userDrugStoreData;
    }

    public Map<Integer, UserDrugChuFangData> getChuFangDataMap() {
        return chuFangDataMap;
    }

    public UserDrugChuFangData getUserDrugChuFangData(int chuFang) {
        return chuFangDataMap.get(chuFang);
    }

    public List<UserDrugLandData> getFarmLandDataList() {
        return farmLandDataList;
    }

    public List<UserDrugChuFangOrderData> getOrderDataList() {
        return orderDataList;
    }

    public List<UserDrugChuFangOrderData> getDoneOrderDataList() {
        return doneOrderDataList;
    }

    /**
     * 构建药铺Builder
     */
    public DrugStoreProto.DrugStoreTemp.Builder getUserDataBuilder() {
        if (userDrugStoreData != null) {
            DrugStoreProto.DrugStoreTemp.Builder builder = DrugStorePb.buildDrugStoreTemp(userDrugStoreData);

            //土地
            for (int i = 0; i < farmLandDataList.size(); i++) {
                UserDrugLandData landData = farmLandDataList.get(i);
                builder.addLand(DrugStorePb.buildDrugLandTemp(landData));
            }
            //订单
            for (int i = 0; i < orderDataList.size(); i++) {
                UserDrugChuFangOrderData orderData = orderDataList.get(i);
                if(orderData.isGetReward()){
                    continue;
                }
                builder.addOrder(DrugStorePb.builderDrugOrderTemp(orderData));
            }
            //处方
            for (Map.Entry<Integer, UserDrugChuFangData> entry : chuFangDataMap.entrySet()) {
                builder.addChuFang(DrugStorePb.buildDrugChuFangTemp(entry.getValue()));
            }
            return builder;
        } else {
            return null;
        }
    }

    /**
     * 增加活动冲榜铜币涨幅
     *
     * @param type 1: 铜币；2：病人数
     */
    public void addActivityScoreRiseData(int value, int type, int time) {
        List<Integer> activityIdList = NormalActivityMgr.getOpenDrugStoreRankActivityIdList();
        Map<Integer, DrugActivityRankValue> rankActivityDataMap = userDrugStoreData.getRankActivityDataMap();
        synchronized (rankActivityDataMap) {
            for (int activityId : activityIdList) {
                ActivityInfo activityInfo = NormalActivityMgr.getActivityInfo(activityId);
                if (!ActivityMgr.activityInTime(activityInfo)) {
                    continue;
                }
                if (activityInfo.getBeginTime() > time){
                    continue;
                }
                if (!rankActivityDataMap.containsKey(activityId)) {
                    DrugActivityRankValue data = new DrugActivityRankValue();
                    data.setActivityId(activityId);
                    rankActivityDataMap.put(activityId, data);
                }
                DrugActivityRankValue data = rankActivityDataMap.get(activityId);
                if (type == 1) {
                    data.setScore(data.getScore() + value);
                } else if (type == 2) {
                    //data.setPatientNum(data.getPatientNum() + value);
                }
                userDrugStoreData.setUpdateOption();
            }
        }
    }

    /*************************************** 疑难杂症 ***************************************/

    /**
     * 解锁疑难杂症
     */
    public DrugStoreProto.DrugStoreUnLockHardCaseRespMsg.Builder unlockHardCase() {
        DrugStoreProto.DrugStoreUnLockHardCaseRespMsg.Builder builder = DrugStoreProto.DrugStoreUnLockHardCaseRespMsg.newBuilder();
        // 判断条件
        if (hardCaseUserData == null || userDrugStoreData == null || userDrugStoreData.getDrugStoreLv() < GameConfig.DRUGSTORE_DIFFICULT_FIRST) {
            builder.setRet(GameErrorCode.E_DRUG_STORE_UNLOCK_LIMIT);
            return builder;
        }
        if (hardCaseUserData.getStatus() != 1) {
            hardCaseUserData.setStatus(1);
        }
        builder.setRet(0);
        builder.setUserInfo(builderDrugStoreHardCaseUserInfo());
        return builder;
    }


    /**
     * 宣传
     *
     * @return
     */
    public DrugStoreProto.DrugStoreHardCasePublicityRespMsg.Builder publicity() {
        DrugStoreProto.DrugStoreHardCasePublicityRespMsg.Builder builder = DrugStoreProto.DrugStoreHardCasePublicityRespMsg.newBuilder();
        if (hardCaseUserData == null || hardCaseUserData.getStatus() == 0) {
            builder.setRet(GameErrorCode.E_DRUG_STORE_NOT_UNLOCK);
            return builder;
        }
        if (hardCaseUserData.getCaseId() != 0) {
            builder.setRet(GameErrorCode.E_DRUG_STORE_HAVE_A_HARD_CASE);
            return builder;
        }
        refreshDrugHardCaseUserData();
        if (hardCaseUserData.getTimes() >= GameConfig.DRUGSTORE_DIFFICULT_MAX_NUM) {
            builder.setRet(GameErrorCode.E_DRUG_STORE_NOT_TIMES);
            return builder;
        }
        // 随机病例
        DrugStorePrescriptionInfo prescriptionInfo = randomHardCasePrescription();
        if (prescriptionInfo == null) {
            builder.setRet(GameErrorCode.E_DRUG_STORE_NOT_HARD_CASE);
            return builder;
        }
        // 判断元宝是否
        Property property = new Property(GameConfig.GAME_MONEY_INGOTS, GameConfig.DRUGSTORE_DIFFICULT_COST);
        if (!player.getModule(CurrencyModule.class).removeCurrency(property, eLogMoneyType.DrugStore, eLogMoneyType.DrugStorePublicityCost)) {
            builder.setRet(GameErrorCode.E_BAG_INGOTS_NO_ENOUGH);
            return builder;
        }
        hardCaseUserData.setCaseId(prescriptionInfo.getId());
        hardCaseUserData.setHealthValue(randomHealth(prescriptionInfo));
        hardCaseUserData.setTimes(hardCaseUserData.getTimes() + 1);
        builder.setRet(0);
        builder.setUserInfo(builderDrugStoreHardCaseUserInfo());

        //加一下平台接口数据
        player.getModule(XiaoMianModule.class).addDrugStorePublicityTimes(1);

        return builder;
    }

    /**
     * 放弃
     *
     * @return
     */
    public DrugStoreProto.DrugStoreHardCaseGiveUpRespMsg.Builder giveUp() {
        DrugStoreProto.DrugStoreHardCaseGiveUpRespMsg.Builder builder = DrugStoreProto.DrugStoreHardCaseGiveUpRespMsg.newBuilder();
        if (hardCaseUserData != null && hardCaseUserData.getCaseId() != 0) {
            AutoLogMgr.add(new LogDrugStoreHardCase(player.getUserId(), hardCaseUserData.getCaseId(), 2, new HashMap<>(), 0, 0, 0, 0, hardCaseUserData.getHealthValue(), 0, ""));
            clearHardCase();
        }
        builder.setRet(0);
        builder.setUserInfo(builderDrugStoreHardCaseUserInfo());
        return builder;
    }

    /**
     * 配药
     */
    public DrugStoreProto.DrugStoreHardCaseDispenseRespMsg.Builder dispense(DrugStoreProto.DrugStoreHardCaseDispense dispense) {
        DrugStoreProto.DrugStoreHardCaseDispenseRespMsg.Builder builder = DrugStoreProto.DrugStoreHardCaseDispenseRespMsg.newBuilder();
        if (hardCaseUserData == null || hardCaseUserData.getStatus() == 0) {
            builder.setRet(GameErrorCode.E_DRUG_STORE_NOT_UNLOCK);
            return builder;
        }
        if (hardCaseUserData.getCaseId() == 0) {
            builder.setRet(GameErrorCode.E_DRUG_STORE_NOT_HARD_CASE);
            return builder;
        }
        // 校验数据
        int ret = checkDispense(dispense, hardCaseUserData.getCaseId());
        if (ret != 0) {
            builder.setRet(ret);
            return builder;
        }
        DrugHardCaseRecordData record = dispenseResult(dispense);
        Property reward = new Property();
        if (record.getScore() == GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_ALL) {
            // 满分
            int num = hardCaseUserData.getFullMap().getOrDefault(record.getCaseId(), 0);
            if (num <= 0) {
                // 首次满分
                DrugStorePrescriptionInfo drugStorePrescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(hardCaseUserData.getCaseId());
                reward.addProperty(PropertyHelper.parseStringToProperty(drugStorePrescriptionInfo.getFirstReward()));
                builder.setFirstFull(true);
            }
            hardCaseUserData.getFullMap().put(record.getCaseId(), num + 1);
            hardCaseUserData.setUpdateOption();
            // 加入配方榜
            DrugStoreMgr.addDispenseList(record);
        }
        // 加buff
        if (ConfigMgr.getDrugHardCaseBuffValueList().size() != 0 && record.getStatus() != 0 && ConfigMgr.getDrugHardCaseBuffValueList().size() >= record.getStatus()) {
            Integer buffValue = ConfigMgr.getDrugHardCaseBuffValueList().get(record.getStatus() - 1);
            if (buffValue != null && buffValue != 0) {
                long endTime = DateHelper.getCurrentTime() + (int) (DateHelper.HOUR_MILLIONS * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_BUFF_TIME);
                addYNZZBuff(buffValue, endTime);
                builder.setBuffValue(buffValue);
                builder.setBuffEndTime(endTime);
            }
        }

        // 加入玩家回答记录
        addHardCaseRecord(record);

        if (ConfigMgr.getDrugHardCaseTimesList().size() != 0 && record.getStatus() != 0 && ConfigMgr.getDrugHardCaseTimesList().size() >= record.getStatus()) {
            int rewardIndex = ConfigMgr.getDrugHardCaseTimesList().get(record.getStatus() - 1);
            // 判断奖励
            if (rewardIndex <= ConfigMgr.getDrugHardCaseRewardList().size()) {
                int boxId = ConfigMgr.getDrugHardCaseRewardList().get(rewardIndex - 1);
                OpenGoodsBagResult result = GoodsBagMgr.getRandomGoods(boxId);
                reward.addProperty(result.getReward());
            }
        }

        // 加奖励
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreHardCaseReward);
        String rewardStr = PropertyHelper.parsePropertyToString(reward);
        // 加入日志
        Map<Integer, Integer> crudeDrugMap = new HashMap<>();
        for (DrugStoreProto.DrugStoreHardCaseCrudeDrug item : dispense.getCrudeDrugListList()){
            crudeDrugMap.put(item.getCrudeDrugId(),item.getNum());
        }
        AutoLogMgr.add(new LogDrugStoreHardCase(player.getUserId(), record.getCaseId(), 1, crudeDrugMap, dispense.getDrugIntroductionId(), dispense.getOrderId(), record.getScore(), record.getStatus(), record.getInitHealth(), record.getFinalHealth(), rewardStr));
        clearHardCase();
        builder.setReward(rewardStr);
        builder.setProcess(buildDrugStoreHardCaseDispenseProcess(record));
        builder.setUserInfo(builderDrugStoreHardCaseUserInfo());
        builder.setRet(0);
        return builder;
    }

    /**
     * 查看疑难杂症病例日志
     *
     * @param caseId
     * @return
     */
    public DrugStoreProto.DrugStoreGetHardCaseRecordRespMsg.Builder getHardCaseRecord(int caseId) {
        DrugStoreProto.DrugStoreGetHardCaseRecordRespMsg.Builder builder = DrugStoreProto.DrugStoreGetHardCaseRecordRespMsg.newBuilder();
        List<DrugHardCaseRecordData> list = new ArrayList<>();
        if (caseId == 0) {
            // 全部
            for (List<DrugHardCaseRecordData> itemList : hardCaseRecordListMap.values()) {
                if(itemList.size() > 0){
                    list.add(itemList.get(0));
                }
            }
        } else {
            List<DrugHardCaseRecordData> tempList = hardCaseRecordListMap.get(caseId);
            if(tempList != null){
                list.addAll(tempList);
            }
        }
        for (DrugHardCaseRecordData item : list) {
            builder.addRecordList(builderDrugStoreHardCaseRecord(item).build());
        }
        builder.setRet(0);
        return builder;
    }

    /**
     * 领取排行榜奖励(配方榜)
     * @param caseId
     * @return
     */
    public DrugStoreProto.DrugStoreReceiveRankRespMsg.Builder receiveRank(int caseId) {
        DrugStoreProto.DrugStoreReceiveRankRespMsg.Builder builder = DrugStoreProto.DrugStoreReceiveRankRespMsg.newBuilder();
        DrugHardCaseUserData userData = getDrugHardCaseUserData(false);
        if(userData == null){
            builder.setRet(GameErrorCode.E_DRUG_STORE_SYSTEM_NOT_UNLOCK);
            return builder;
        }
        if (userData.getReceiveList().contains(caseId)) {
            // 不能重复领取
            builder.setRet(GameErrorCode.E_DRUG_STORE_REWARD_HAS_BEEN_RECEIVED);
            return builder;
        }
        DrugStorePrescriptionInfo drugStorePrescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(caseId);
        // 加奖励
        player.getModule(CurrencyModule.class).addCurrency(drugStorePrescriptionInfo.getRewards(), eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreHardCaseDispenseReward);
        userData.getReceiveList().add(caseId);
        userData.setUpdateOption();
        builder.setReward(drugStorePrescriptionInfo.getRewards());
        builder.setUserInfo(builderDrugStoreHardCaseUserInfo());
        builder.setRet(0);
        return builder;
    }


    private DrugHardCaseUserData getDrugHardCaseUserData(boolean newIfNull) {
        if (hardCaseUserData == null && newIfNull) {
            hardCaseUserData = new DrugHardCaseUserData();
            hardCaseUserData.setUserId(player.getUserId());
            hardCaseUserData.setStatus(0);
            hardCaseUserData.setTimes(0);
            hardCaseUserData.setRefreshTime(DateHelper.getCurrentSecond());
            hardCaseUserData.setInsertOption();
        }
        return hardCaseUserData;
    }


    /**
     * 随机疑难杂症病例
     */
    private DrugStorePrescriptionInfo randomHardCasePrescription(){
        DrugStoreBadgeInfo badgeInfo = DrugStoreConfigMgr.getDrugStoreBadgeInfo(userDrugStoreData.getDrugStoreLv());
        if(badgeInfo == null){
            return null;
        }
        List<String> typeWeightList = StringUtils.stringToStringList(badgeInfo.getExParam(), "#");
        if(typeWeightList.size() > 0) {
            List<String> weightItemList = StringUtils.stringToStringList(typeWeightList.get(1), "\\|");
            HashMap<Integer, Integer> map = new HashMap<>();
            for (String str : weightItemList) {
                List<Integer> idWeightList = StringUtils.stringToIntegerList(str, ";");
                if (idWeightList.size() == 2) {
                    int times = hardCaseUserData.getFullMap().getOrDefault(idWeightList.get(0),0);
                    int weight = Math.max(GameConfig.DRUGSTORE_DIFFICULT_WEIGHT_SAVE, idWeightList.get(1) - times * GameConfig.DRUGSTORE_DIFFICULT_WEIGHT_FIX);
                    map.put(idWeightList.get(0), weight);
                }
            }
            logger.info("疑难杂症宣传权重打印，userId:{},map:{}",player.getUserId(), JSON.toJSONString(map));
            int id = WeightHelper.getRandomValue(map);
            return DrugStoreConfigMgr.getDrugStorePrescriptionInfo(id);
        }
        return null;
    }

    /**
     * 添加疑难杂症记录
     */
    private void addHardCaseRecord(DrugHardCaseRecordData record) {
        List<DrugHardCaseRecordData> list = hardCaseRecordListMap.get(record.getCaseId());
        if (list == null) {
            list = new ArrayList<>();
            hardCaseRecordListMap.put(record.getCaseId(), list);
        }
        list.add(record);
        synchronized (saveDrugHardCaseRecordDataList){
            saveDrugHardCaseRecordDataList.add(record);
        }
        // 排序规则 第一个是分数最高的 并且时间最大的  其他按时间排序
        hardCaseRecordSort(record.getCaseId());
    }

    public Map<Integer, List<DrugHardCaseRecordData>> getHardCaseRecordListMap() {
        return hardCaseRecordListMap;
    }

    /**
     * @param caseId
     */
    private void hardCaseRecordSort(int caseId) {
        List<DrugHardCaseRecordData> list = hardCaseRecordListMap.get(caseId);
        if(list.size() <= 0){
            return;
        }
        // 排序规则 第一个是分数最高的 并且时间最大的  其他按时间排序
        list.sort((t1,t2)->{
            if(t1.getScore() != t2.getScore()){
                return Integer.compare(t2.getScore(), t1.getScore());
            }else {
                return Long.compare(t2.getTime(), t1.getTime());
            }
        });
        DrugHardCaseRecordData maxScoreRecord = list.remove(0);
        list.sort((t1,t2)->{
            return Long.compare(t2.getTime(), t1.getTime());
        });
        List<DrugHardCaseRecordData> tempList = new ArrayList();
        tempList.add(maxScoreRecord);
        tempList.addAll(list);
        while (tempList.size() > 0 && tempList.size() > GameConfig.DRUGSTORE_DIFFICULT_HIGHT_SCORE_NUM){
            tempList.remove(tempList.size() - 1);
        }
        hardCaseRecordListMap.put(caseId, tempList);
    }

    /**
     * 随机健康值
     *
     * @param prescriptionInfo
     * @return
     */
    private int randomHealth(DrugStorePrescriptionInfo prescriptionInfo) {
        List<String> list = StringUtils.stringToStringList(prescriptionInfo.getExParam(), ";");
        int minValue = Integer.valueOf(list.get(0));
        int maxValue = Integer.valueOf(list.get(1)) + 1;
        return new Random().nextInt(maxValue - minValue) + minValue;
    }


    /**
     * 步骤一把评分按权重分给药引、医嘱、药材
     * 步骤二具体分数计算
     * <p>
     * 配药 评分
     *
     * @param dispense
     */
    private DrugHardCaseRecordData dispenseResult(DrugStoreProto.DrugStoreHardCaseDispense dispense) {
        DrugHardCaseRecordData record = new DrugHardCaseRecordData();
        record.setUserId(player.getUserId());
        record.setCaseId(hardCaseUserData.getCaseId());
        record.setInitHealth(hardCaseUserData.getHealthValue());
        record.setFinalHealth(hardCaseUserData.getHealthValue());
        DrugStorePrescriptionInfo drugStorePrescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(hardCaseUserData.getCaseId());
        // 正确的配方
        DrugStorePrescriptionDispenseInfo dispenseInfo = drugStorePrescriptionInfo.getDispenseInfo();
        // 初始健康
        int initHealth = hardCaseUserData.getHealthValue();
        // 药材总分数 (放大100 倍)
        int crudeDrugScore = ConfigMgr.getDrugHardCaseWeight().get(0) * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_ALL * 100 / ConfigMgr.getDrugHardCaseTotalWeightValue();
        // 药引总分数 (放大100 倍)
        int drugIntroductionTotalScore = ConfigMgr.getDrugHardCaseWeight().get(1) * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_ALL * 100 / ConfigMgr.getDrugHardCaseTotalWeightValue();
        // 医嘱总分数 (放大100 倍)
        int orderIdTotalScore = ConfigMgr.getDrugHardCaseWeight().get(2) * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_ALL * 100 / ConfigMgr.getDrugHardCaseTotalWeightValue();
        // 每个药材的分数 (放大100 倍)
        int T = crudeDrugScore / dispenseInfo.getCrudeDrugMap().size();
        // 确定 传入的药材 跟 正确的药材 的对应
        // k:传入的药材 v:比对的药材
        Map<Integer, DrugHardCaseCoincidenceDegree> map = new HashMap<>();
        // 玩家传入的药材
        List<DrugStoreProto.DrugStoreHardCaseCrudeDrug> userCaseCrudeDrugList = new ArrayList<>(dispense.getCrudeDrugListList());
        // 正确的药材
        List<Integer> crudeDrugList = new ArrayList<>(dispenseInfo.getCrudeDrugMap().keySet());
        // 计算所有药材的重合度
        for (int i = 0; i < dispense.getCrudeDrugListList().size(); i++) {
            int maxCoincidenceDegree = 0;
            Integer maxCrudeDrugId = 0;
            DrugStoreProto.DrugStoreHardCaseCrudeDrug maxDrugStoreHardCaseCrudeDrug = null;
            for (DrugStoreProto.DrugStoreHardCaseCrudeDrug item : userCaseCrudeDrugList) {
                GoodsInfo goodsInfo = GoodsMgr.getGoodsById(item.getCrudeDrugId());
                // 重合度
                for (int correctId : crudeDrugList) {
                    GoodsInfo correctCrudeDrug = GoodsMgr.getGoodsById(correctId);
                    // 对比的药材属性
                    List<Integer> crudeDrugPropertyList = StringUtils.stringToIntegerList(goodsInfo.getExtendParam(), "\\|");
                    // 正确药材的属性
                    List<Integer> correctCrudeDrugPropertyList = StringUtils.stringToIntegerList(correctCrudeDrug.getExtendParam(), "\\|");
                    int maxNum = Math.max(crudeDrugPropertyList.size(), correctCrudeDrugPropertyList.size());
                    // 重合度
                    int correctNum = 0;
                    for (Integer propertyId : crudeDrugPropertyList) {
                        if (correctCrudeDrugPropertyList.contains(propertyId)) {
                            correctNum++;
                        }
                    }
                    // 放大100
                    int coincidenceDegree = correctNum * 100/ maxNum;
                    if (maxCoincidenceDegree == 0 || coincidenceDegree > maxCoincidenceDegree || (coincidenceDegree == maxCoincidenceDegree && maxDrugStoreHardCaseCrudeDrug.getCrudeDrugId() > item.getCrudeDrugId())) {
                        // 重合度大 或者 重合度一样 id小
                        maxCoincidenceDegree = coincidenceDegree;
                        maxCrudeDrugId = correctId;
                        maxDrugStoreHardCaseCrudeDrug = item;
                    }
//                    logger.info("疑难杂症计算重合度，userId:{},传入的药材id:{},比对的药材id：{},重合度：{},病例id:{}", player.getUserId(), item.getCrudeDrugId(), correctId, coincidenceDegree, hardCaseUserData.getCaseId());
                }
            }
            // 找出重合度最高的匹配
            if(maxDrugStoreHardCaseCrudeDrug == null){
                continue;
            }
            Iterator<DrugStoreProto.DrugStoreHardCaseCrudeDrug> iterator = userCaseCrudeDrugList.iterator();
            while (iterator.hasNext()){
                DrugStoreProto.DrugStoreHardCaseCrudeDrug item = iterator.next();
                if(item.getCrudeDrugId() == maxDrugStoreHardCaseCrudeDrug.getCrudeDrugId()){
                    iterator.remove();
                    break;
                }
            }
            //userCaseCrudeDrugList.remove(maxDrugStoreHardCaseCrudeDrug);
            crudeDrugList.remove(maxCrudeDrugId);
            DrugHardCaseCoincidenceDegree caseCoincidenceDegree = new DrugHardCaseCoincidenceDegree(maxDrugStoreHardCaseCrudeDrug.getCrudeDrugId(), maxDrugStoreHardCaseCrudeDrug.getNum(), maxCoincidenceDegree);
            map.put(maxCrudeDrugId, caseCoincidenceDegree);
        }
//        logger.info("疑难杂症计算药材对比信息，userId:{},map:{}", player.getUserId(), JSONObject.toJSONString(map));
        // 按正常药材的顺序计算
        for (Integer correctId : dispenseInfo.getCrudeDrugList()) {
            // 1 计算得分
            DrugHardCaseCoincidenceDegree caseCoincidenceDegree = map.get(correctId);
            // 正确的数量
            int correctNum = dispenseInfo.getCrudeDrugMap().getOrDefault(correctId, 0);
            // 计算重合度 N
            int N = caseCoincidenceDegree.getCoincidenceDegree();
            // 计算药量参数 L
            int L = Math.abs(correctNum - caseCoincidenceDegree.getNum());
            // 得分 放大100
            int S = 0;
            if (N > 0) {
                S = T * N / (GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_SINGLE_PARAM_2 * 100 + L * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_SINGLE_PARAM_1 / 10);
            } else {
                S = -GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_DRUG_DEDUCT * caseCoincidenceDegree.getNum() * 100;
            }
            // 2 计算健康值
            int healthChange = calHealthChange(T, S, initHealth, record, false);

            record.getCrudeDrugList().add(new DrugStoreHardCaseDispenseResultInfo(caseCoincidenceDegree.getCrudeDrugId(), caseCoincidenceDegree.getNum(), correctId, healthChange, S));
//            logger.info("疑难杂症药材 分数、健康值计算，userId:{},caseId;{},正确的药：{}，要对比的药：{}，重合度N：{},计算药量参数L:{},药材的总分数T：{}，药材得S:{},最终评分：{}，改变的健康值：{}，最终健康值：{}", player.getUserId(), hardCaseUserData.getCaseId(), correctId, caseCoincidenceDegree.getCrudeDrugId(), N, L, T, S, record.getScore(), healthChange, record.getFinalHealth());
        }
        // 药引得分
        DrugStoreHardCaseDispenseResultInfo drugIntroductionResult = new DrugStoreHardCaseDispenseResultInfo();
        drugIntroductionResult.setId(dispense.getDrugIntroductionId());
        drugIntroductionResult.setCorrectId(dispenseInfo.getDrugIntroductionId());
        // 药引实际得分
        int drugIntroductionScore = 0;
        if (dispense.getDrugIntroductionId() == dispenseInfo.getDrugIntroductionId()) {
            drugIntroductionScore = drugIntroductionTotalScore;
        }
        int drugIntroductionHealthChange = calHealthChange(drugIntroductionTotalScore, drugIntroductionScore, initHealth, record, false);

        drugIntroductionResult.setHealth(drugIntroductionHealthChange);
//        logger.info("疑难杂症药引 分数、健康值计算，userId:{},caseId;{},正确的药引:{}，传入的药引：{}，药引的总分数T：{}，最终评分：{}，改变的健康值：{}，最终健康值：{}", player.getUserId(), hardCaseUserData.getCaseId(), dispenseInfo.getDrugIntroductionId(), dispense.getDrugIntroductionId(), drugIntroductionTotalScore, record.getScore(), drugIntroductionHealthChange, record.getFinalHealth());
        record.setDrugIntroductionInfo(drugIntroductionResult);
        // 医嘱得分
        DrugStoreHardCaseDispenseResultInfo orderResult = new DrugStoreHardCaseDispenseResultInfo();
        orderResult.setId(dispense.getOrderId());
        orderResult.setCorrectId(dispenseInfo.getOrderId());
        // 医嘱实际得分
        int orderIdScore = 0;
        boolean isRoundUp = false;
        if (dispense.getOrderId() == dispenseInfo.getOrderId()) {
            orderIdScore = orderIdTotalScore;
            isRoundUp = true;
        }
        int orderHealthChange = calHealthChange(orderIdTotalScore, orderIdScore, initHealth, record ,isRoundUp);
        orderResult.setHealth(orderHealthChange);
        if(record.getScore() < 0){
            record.setScore(0);
        }
//        logger.info("疑难杂症医嘱 分数、健康值计算，userId:{},caseId;{},正确的医嘱:{}，传入的医嘱：{}，药引的总分数T：{}，最终评分：{}，改变的健康值：{}，最终健康值：{}", player.getUserId(), hardCaseUserData.getCaseId(), dispenseInfo.getOrderId(), dispense.getOrderId(), orderIdTotalScore, record.getScore(), orderHealthChange, record.getFinalHealth());
        record.setOrderInfo(orderResult);

        record.setTime(DateHelper.getCurrentSecond());
        // 计算健康等级
        record.setStatus(calHealLevel(initHealth, record.getFinalHealth()).getValue());
        record.setInsertOption();
        return record;
    }


    /**
     * 计算健康变化量
     *
     * @param T         分值
     * @param S         评分
     * @param initHealth 初始健康值
     * @param record
     * @param isRoundUp 是否向上取整
     * @return
     */
    private int calHealthChange(int T, int S, int initHealth, DrugHardCaseRecordData record, boolean isRoundUp) {
        int healthChange = 0;
        int A = T * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_HEALTHY_ANCHOR / 100;
        if (S > A) {
            // 增加健康值
            healthChange = T * (GameConfig.DRUGSTORE_DIFFICULT_EVALUE_HEALTHY_MAX - initHealth) * (S - A) / (GameConfig.DRUGSTORE_DIFFICULT_EVALUE_SCORE_ALL * (T - A));
        } else {
            // 减少健康值
            healthChange = -((A - S) * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_HEALTHY_REDUCE_PARAM / 100);
        }
        // 累计健康值余数
        int addHealth = healthChange + record.getHealthRemainNum();
        healthChange = (addHealth) / 100;
        record.setHealthRemainNum(addHealth % 100);
        record.setFinalHealth(record.getFinalHealth() + healthChange);
        // 累计分数余数
        int addScore = S + record.getScoreRemainNum();
        record.setScoreRemainNum(addScore % 100);
        record.setScore(record.getScore() + addScore / 100);

        if(isRoundUp){
            if(record.getHealthRemainNum() > 0 && record.getFinalHealth() < 100){
                record.setFinalHealth(record.getFinalHealth() + 1);
                healthChange++;
            }
            if(record.getScoreRemainNum() > 0 && record.getScore() < 100){
                record.setScore(record.getScore() + 1);
            }
        }
        return healthChange;
    }

    /**
     * 计算最终健康值影响评价
     *
     * @param initHealth
     * @param finalHealth
     * @return
     */
    private eDrugHardCaseHealthStatus calHealLevel(double initHealth, double finalHealth) {
        if (finalHealth <= ConfigMgr.getHealthEvaluationList().get(0)[1]) {
            // 一命呜呼
            return eDrugHardCaseHealthStatus.STATUS_1;
        } else if (finalHealth >= ConfigMgr.getHealthEvaluationList().get(1)[0] && finalHealth <= ConfigMgr.getHealthEvaluationList().get(1)[1]) {
            // 奄奄一息
            return eDrugHardCaseHealthStatus.STATUS_2;
        } else if (finalHealth >= ConfigMgr.getHealthEvaluationList().get(3)[0]) {
            // 药到病除 / 妙手回春
            return eDrugHardCaseHealthStatus.STATUS_7;
        } else {
            if (initHealth > finalHealth) {
                // 病情加重
                return eDrugHardCaseHealthStatus.STATUS_3;
            } else if (initHealth == finalHealth) {
                // 未见药效
                return eDrugHardCaseHealthStatus.STATUS_4;
            } else {
                if (finalHealth - initHealth < (100 - initHealth) * GameConfig.DRUGSTORE_DIFFICULT_EVALUE_LINE / 100) {
                    //稍见好转
                    return eDrugHardCaseHealthStatus.STATUS_5;
                } else {
                    //大有起色
                    return eDrugHardCaseHealthStatus.STATUS_6;
                }
            }
        }
    }


    /**
     * 刷新玩家疑难杂症数据
     */
    private void refreshDrugHardCaseUserData() {
        if (DateHelper.getDiffDayNum(hardCaseUserData.getRefreshTime()) != 0) {
            synchronized (hardCaseUserData){
                if (DateHelper.getDiffDayNum(hardCaseUserData.getRefreshTime()) != 0) {
                    hardCaseUserData.setRefreshTime(DateHelper.getCurrentSecond());
                    hardCaseUserData.setTimes(0);
                }
            }
        }
    }

    /**
     * 放弃疑难杂症
     */
    private void clearHardCase() {
        if (hardCaseUserData != null) {
            hardCaseUserData.setCaseId(0);
            hardCaseUserData.setHealthValue(0);
        }
    }

    /**
     * 铜板榜单变更
     */
    private void changeValueRank() {
        try {
            RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), BigInteger.valueOf(userDrugStoreData.getTongBi()), eRankType.DrugStroeTongBiValue.getValue(),"" + userDrugStoreData.getDrugStoreLv());
        } catch (Exception ex) {
            log.error(ex);
        }
    }

    /**
     * 校验客户端传过来的配方数据
     * @param dispense
     * @return
     */
    public int checkDispense(DrugStoreProto.DrugStoreHardCaseDispense dispense,int caseId){
        DrugStorePrescriptionInfo drugStorePrescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(caseId);
        // 正确的配方
        DrugStorePrescriptionDispenseInfo dispenseInfo = drugStorePrescriptionInfo.getDispenseInfo();
        HashSet<Integer> set = new HashSet<>();
        for(DrugStoreProto.DrugStoreHardCaseCrudeDrug item : dispense.getCrudeDrugListList()){
            set.add(item.getCrudeDrugId());
            if(item.getNum() <= 0){
                // 数量小于等于0
                return GameErrorCode.E_DRUG_STORE_NUM_ERROR;
            }
            // 判断传进来的药 是药材
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(item.getCrudeDrugId());
            if(goodsInfo == null){
                return GameErrorCode.E_DRUG_STORE_CURDE_DRUG_NO_EXIST;
            }
        }
        if(set.size() != dispense.getCrudeDrugListCount()){
            // 配方药材重复
            return GameErrorCode.E_DRUG_STORE_CURDE_DRUG_REPEAT;
        }
        if(set.size() <= 0 || set.size() != dispenseInfo.getCrudeDrugList().size()){
            // 配方药材数量不对
            return GameErrorCode.E_DRUG_STORE_CURDE_DRUG_NUM_ERROR;
        }
        return 0;
    }


    public DrugStoreProto.DrugStoreHardCaseUserInfo.Builder builderDrugStoreHardCaseUserInfo() {
        DrugStoreProto.DrugStoreHardCaseUserInfo.Builder builder = DrugStoreProto.DrugStoreHardCaseUserInfo.newBuilder();
        if (hardCaseUserData != null) {
            // 刷新次数
            refreshDrugHardCaseUserData();
            builder.setStatus(hardCaseUserData.getStatus());
            builder.setTimes(hardCaseUserData.getTimes());
            builder.setCaseId(hardCaseUserData.getCaseId());
            builder.setHealthValue(hardCaseUserData.getHealthValue());
            builder.setRefreshTime(hardCaseUserData.getRefreshTime());
            hardCaseUserData.getReceiveList().forEach(e -> {
                builder.addReceiveList(e);
            });
        }
        return builder;
    }

    public DrugStoreProto.DrugStoreHardCaseDispenseProcess.Builder buildDrugStoreHardCaseDispenseProcess(DrugHardCaseRecordData recordData) {
        DrugStoreProto.DrugStoreHardCaseDispenseProcess.Builder process = DrugStoreProto.DrugStoreHardCaseDispenseProcess.newBuilder();
        process.setInitHealth(recordData.getInitHealth());
        process.setFinalHealth(recordData.getFinalHealth());
        recordData.getCrudeDrugList().forEach(e -> {
            process.addCrudeDrugList(builderDrugStoreHardCaseDispenseResult(e));
        });
        process.setDrugIntroduction(builderDrugStoreHardCaseDispenseResult(recordData.getDrugIntroductionInfo()));
        process.setOrder(builderDrugStoreHardCaseDispenseResult(recordData.getOrderInfo()));
        process.setInitHealth(recordData.getInitHealth());

        process.setScore(recordData.getScore());
        process.setStatus(recordData.getStatus());
        return process;
    }

    public DrugStoreProto.DrugStoreHardCaseDispenseResult.Builder builderDrugStoreHardCaseDispenseResult(DrugStoreHardCaseDispenseResultInfo resultInfo) {
        DrugStoreProto.DrugStoreHardCaseDispenseResult.Builder builder = DrugStoreProto.DrugStoreHardCaseDispenseResult.newBuilder();
        builder.setId(resultInfo.getId());
        builder.setNum(resultInfo.getNum());
        builder.setCorrectId(resultInfo.getCorrectId());
        builder.setHealth(resultInfo.getHealth());
        return builder;
    }

    public DrugStoreProto.DrugStoreHardCaseRecord.Builder builderDrugStoreHardCaseRecord(DrugHardCaseRecordData recordData) {
        DrugStoreProto.DrugStoreHardCaseRecord.Builder process = DrugStoreProto.DrugStoreHardCaseRecord.newBuilder();
        process.setCaseId(recordData.getCaseId());
        process.setProcess(buildDrugStoreHardCaseDispenseProcess(recordData));
        process.setTime(recordData.getTime());
        return process;
    }

    public long getReceiveCount() {
        long count = 0;
        if(userDrugStoreData != null) {
            count = userDrugStoreData.getReceiveNum();
        }
        return count;
    }

    public int getTechnologyAdd(UserBuilding userBuilding) {
        if(userDrugStoreData == null){
            return 0;
        }
        List<DrugStoreTeach> teachList = userDrugStoreData.getTechList();
        return DrugStoreMgr.getTechnologyAdd(teachList, userBuilding);
    }

    public void addExperience(int goodsId, long longValue, eLogMoneyType master, eLogMoneyType son) {
        if(userDrugStoreData != null){
            synchronized (userDrugStoreData){
                userDrugStoreData.setExperience(longValue + userDrugStoreData.getExperience());
            }
            player.notifyListener(eGamePlayerEventType.DrugStoreScoreRise.getValue(),longValue);
        }
    }

    /**
     * 更新勋章
     */
    public void updateBadge() {
        if (SystemOpenMgr.systemOpen(player, eSystemId.BadgeShow.getValue())) {
            if (userDrugStoreData == null) {
                return;
            }
            DrugStoreBadgeInfo badgeInfo = DrugStoreConfigMgr.getDrugStoreBadgeInfo(userDrugStoreData.getDrugStoreLv());
            if (badgeInfo == null) {
                return;
            }
            player.getModule(BadgeModule.class).addBadge(badgeInfo.getId(), eBadgeType.DrugStore.getValue());
        }
    }

    /**
     * V5.5 药铺找回奖励
     */
    public RecoveryRewardProto.RecoverDrugStoryMsg.Builder recoverDrugStoreReward(int times) {
        RecoveryRewardProto.RecoverDrugStoryMsg.Builder returnBuilder = RecoveryRewardProto.RecoverDrugStoryMsg.newBuilder();

        List<DrugOrderReward> orderRewardList = new ArrayList<>();
        for (int i = 0; i < times; i++) {          //随机人数 奖励汇总
            //随机处方
            DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.randomUnLockChuFang(userDrugStoreData.getDrugStoreLv());
            if (prescriptionInfo == null) {
                return null;
            }

            UserDrugChuFangData chuFangData = getUserDrugChuFangData(prescriptionInfo.getId());
            if (chuFangData == null) {
                return null;
            }
            List<DrugOrderNeed> list = DrugStoreMgr.generateOrderDrugNeed(chuFangData.getChuFang());
            //接待人数
            userDrugStoreData.setReceiveNum(userDrugStoreData.getReceiveNum() + 1);
            DrugOrderReward reward = calOrderReward(chuFangData.getChuFang(), chuFangDataMap.get(chuFangData.getChuFang()).getLv(), list, (int) (System.currentTimeMillis() / 1000));
            orderRewardList.add(reward);
            Property logReward = new Property();
            logReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(reward.getTb()));
            logReward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(reward.getExp()));
            AutoLogMgr.add(new LogDrugStoreOrder(player.getUserId(), -1, new Date(), new Date(), new Date(), chuFangData.getChuFang(), chuFangData.getLv(), 1, "",
                    PropertyHelper.parsePropertyToString(logReward)));
        }
        //更新病人数成就 只加这一个总成就 加log

        player.notifyListener(eGamePlayerEventType.DrugStoreReceiveNumLevel.getValue(), BigInteger.valueOf(userDrugStoreData.getReceiveNum()));

        AutoLogMgr.add(new LogDrugStoreReceive(player.getUserId(), 3, times));

        Property reward = new Property();
        DrugStoreProto.DrugStoreShuLianDuSync.Builder shuLianDuSync = DrugStoreProto.DrugStoreShuLianDuSync.newBuilder();


        for (DrugOrderReward orderReward : orderRewardList) {
            DrugStorePrescriptionInfo prescriptionInfo = DrugStoreConfigMgr.getDrugStorePrescriptionInfo(orderReward.getCf());
            if (prescriptionInfo == null) {
                continue;
            }
            reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_EXP, BigInteger.valueOf(orderReward.getExp()));
            reward.addProperty(GameConfig.DRUGSTORE_ITEM_ID_MONEY, BigInteger.valueOf(orderReward.getTb()));
            //熟练度
            UserDrugChuFangData chuFangData = getChuFangDataMap().get(orderReward.getCf());
            if (chuFangData != null) {
                chuFangData.setShuLianDu(chuFangData.getShuLianDu() + orderReward.getSld());
                shuLianDuSync.addChuFang(DrugStorePb.buildDrugChuFangTemp(chuFangData));
            }

            DrugStoreProto.DrugTreasureBowlRewardTemp.Builder rewardBuild = DrugStorePb.buildTreasureBowlReward(orderReward);
            returnBuilder.addBowlReward(rewardBuild);

            //addActivityScoreRiseData((int)orderReward.getTb(), 1, orderReward.getT());找回不冲榜
        }
        userDrugStoreData.setTongBi(reward.getCountByGoodsId(GameConfig.DRUGSTORE_ITEM_ID_MONEY).intValue() + userDrugStoreData.getTongBi());
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DrugStore, eLogMoneyType.DrugStoreBowlReward);

        DrugStoreProto.DrugTreasureBowlRewardRespMsg.Builder respMsg = DrugStoreProto.DrugTreasureBowlRewardRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        respMsg.setExperience(userDrugStoreData.getExperience());
        respMsg.setTongBi(userDrugStoreData.getTongBi());
        returnBuilder.setBowlResp(respMsg);
        //熟练度更新客户端
        player.sendPacket(Protocol.U_DRUG_STORE_SHU_LIAN_DU_SYNC, shuLianDuSync);
        return returnBuilder;
    }

    public int getLastSaveTimePower() {
        return lastSaveTimePower;
    }
}
